Base Station (hdu 3879 最大权闭合图)

Base Station

Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65768/32768 K (Java/Others)

Total Submission(s): 1983    Accepted Submission(s): 838

Problem Description

A famous mobile communication company is planning to build a new set of base stations. According to the previous investigation, n places are chosen as the possible new locations to build those new stations. However, the condition of each position varies much,
so the costs to built a station at different places are different. The cost to build a new station at the ith place is Pi (1<=i<=n).

When complete building, two places which both have stations can communicate with each other.

Besides, according to the marketing department, the company has received m requirements. The ith requirement is represented by three integers Ai, Bi and Ci, which means if place Aand Bi can communicate
with each other, the company will get Ci profit.

Now, the company wants to maximize the profits, so maybe just part of the possible locations will be chosen to build new stations. The boss wants to know the maximum profits.

Input

Multiple test cases (no more than 20), for each test case:

The first line has two integers n (0<n<=5000) and m (0<m<=50000).

The second line has n integers, P1 through Pn, describes the cost of each location.

Next m line, each line contains three integers, Ai, Bi and Ci, describes the ith requirement.

Output

One integer each case, the maximum profit of the company.

Sample Input

5 5
1 2 3 4 5
1 2 3
2 3 4
1 3 3
1 4 2
4 5 3

Sample Output

4

Author

liulibo

Source

2011 Multi-University Training Contest 5 - Host
by BNU

Recommend

lcy   |   We have carefully selected several similar problems for you:  3657 1565 3491 3887 3889

题意:有n个地方可供建造基站,建造每个基站有一个成本p,有m个用户群,第i个用户群的用户会使用基站ai和bi进行通讯,公司获利ci,公司有选择的修建基站,问最大的净利润为多少。净利润=总收益-总成本。

思路:首先分析题目中的决策因素。在满足了第i个用户群后,便可以得到收益,然而满足第 个用户群需要有必要条件:建立中转站ai和中转站bi,同时要花去相应费用。留心这个所谓 的必要条件,便可联想到闭合图的性质。分析后发现,本题就是最大权闭合图的一个特例。把它抽象成这样一个有向图模型:每个用户群i作为一个结点分别向相应的中转站ai和中转站bi 连有向边。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 55005
#define MAXM 555005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

struct Edge
{
    int u,v,cap,next;
}edge[MAXM];

int head[maxn],cur[maxn],level[maxn];
int num,n,m;

void init()
{
    num=0;
    mem(head,-1);
}

void addedge(int u,int v,int w)
{
    edge[num].u=u; edge[num].v=v; edge[num].cap=w; edge[num].next=head[u]; head[u]=num++;
    edge[num].u=v; edge[num].v=u; edge[num].cap=0; edge[num].next=head[v]; head[v]=num++;
}

bool bfs(int s,int t)
{
    mem(level,-1);
    queue<int>Q;
    level[s]=0;
    Q.push(s);
    while (!Q.empty())
    {
        int u=Q.front();Q.pop();
        for (int i=head[u];i+1;i=edge[i].next)
        {
            int v=edge[i].v;
            if (edge[i].cap>0&&level[v]==-1)
            {
                level[v]=level[u]+1;
                Q.push(v);
            }
        }
    }
    return level[t]!=-1;
}

int dfs(int u,int t,int f)
{
    if (u==t) return f;
    for (int &i=cur[u];i+1;i=edge[i].next)
    {
        int v=edge[i].v;
        if (edge[i].cap>0&&level[v]==level[u]+1)
        {
            int d=dfs(v,t,min(f,edge[i].cap));
            if (d>0)
            {
                edge[i].cap-=d;
                edge[i^1].cap+=d;
                return d;
            }
        }
    }
    return 0;
}

int dinic(int s,int t,int nodenum)
{
    int flow=0;
    while (bfs(s,t))
    {
        for (int i=0;i<nodenum+1;i++) cur[i]=head[i];
        int f;
        while ((f=dfs(s,t,INF))>0)
               flow+=f;
    }
    return flow;
}

int main()
{
//    freopen("C:/Users/asus1/Desktop/IN.txt","r",stdin);
    int i,j,u,v,w;
    while (~sff(n,m))
    {
        int sum=0;
        init();
        for (i=1;i<=n;i++)
        {
            scanf("%d",&w);
            addedge(m+i,n+m+1,w);
        }
        for (i=1;i<=m;i++)
        {
            sfff(u,v,w);
            sum+=w;
            addedge(0,i,w);
            addedge(i,u+m,INF);
            addedge(i,v+m,INF);
        }
        printf("%d\n",sum-dinic(0,n+m+1,n+m+2));
    }
    return 0;
}
时间: 2024-10-05 13:42:11

Base Station (hdu 3879 最大权闭合图)的相关文章

hdu 3879 最大权闭合图(裸题)

/* 裸的最大权闭合图 解:参见胡波涛的<最小割模型在信息学竞赛中的应用> */ #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> using namespace std; #define N 55100//刚开始开的是5100一直越界应该是n+m #define NN 510000 #define inf 0x3fffffff struct node

hdu 3061 hdu 3996 最大权闭合图 最后一斩

hdu 3061 Battle :一看就是明显的最大权闭合图了,水提......SB题也不说边数多少....因为开始时候数组开小了,WA....后来一气之下,开到100W,A了.. hdu3996.  gold mine..看了一下,简单题,几乎裸,不敲了.. #include<iostream>//Battle #include<queue> #include<cstdio> #include<cstring> #include<set> #i

hdu 3917 最大权闭合图

/*最大权闭合图: 题意:一些城市需要建路需要一些公司来负责,每个公司需要交一定的税,每条路需要给公司一定的花费,还有一个限制条件,假如说公司a建立了a-b,公司b建立了b-c那么选择 公司a 那么必须选择公司b. 现在要求最大收益. 解:设置一个源点和汇点,将选每个公司的收益和算出来,如果为正值和源点相连,如果为负值和和汇点相连权值为其绝对值,中间的公司之间有关系的权值置为inf, 最大权闭合图=所有正收益的和-最小割. */ #include<stdio.h> #include<st

hdu 2987最大权闭合图模板类型题

/* 最大权闭合图模板类型的题,考验对知识概念的理解. 题意:现在要辞退一部分员工,辞退每一个员工可以的到一部分利益(可以是负的),并且辞退员工,必须辞退他的下属,求最大利益和辞退的最小人数. 最大权闭合图模板类型. 求出最大权后沿着源点s,dfs到的点就为最小的人数. 证明/* 转载:利用一个经典的trick:多关键字 > 建图前,对所有b[i],执行变换b[i]=b[i]*10000-1,然后,会惊异地发现, > 此时最大流所对应的方案就是满足辞退最少人数的了. > 为什么?显然,变

Road constructions (hdu 3917 最大权闭合图)

Road constructions Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1436    Accepted Submission(s): 467 Problem Description N cities are required to connect with each other by a new transportati

HDU 3917 最大权闭合图 求最小割

具体参考http://blog.csdn.net/power721/article/details/6665750 TODO 1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #define N 8005 5 #define M 1000005 6 #define inf 999999999 7 #define min(a,b) ((a)<(b)?(a):(b)) 8 using namespa

Battle (hdu 3061 最大权闭合图模板题)

Battle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 963    Accepted Submission(s): 463 Problem Description 由于小白同学近期习武十分刻苦,很快被晋升为天策军的统帅.而他上任的第一天,就面对了一场极其困难的战斗: 据侦查兵回报,前方共有N座城池,考虑到地势原因,最终得到一个结

HDU 3879:Base Station(最大权闭合图)

http://acm.hdu.edu.cn/showproblem.php?pid=3879 http://www.lydsy.com/JudgeOnline/problem.php?id=1497 题意:给出n个点m条边,其中每个点有一个权值代表修建这个点需要耗费的钱,然后m条边里面,代表如果两个修建好的点相连的话,那么可以得到一点利润.求最大的获利. 思路:和BZOJ 1497是同一道题目.学习最大权闭合图的题目,看了一下不清楚应该怎么建图,然后只好搜一个论文来看看.http://wenku

HDU 3879 Base Station 最大权闭合图

题目链接:点击打开链接 题意: 给定n个带权点m条无向带权边 选一个子图,则这个子图的权值为 边权和-点权和 求一个最大的权值 把边也当成点.然后是最大权闭合图 dinic: #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; //点标 从0开始 F.Init(n) n=最大点标+10 const int N =