hdu 3879 Base Station 网络流 最大权闭合图

最大权闭合图的证明:http://www.cnblogs.com/wuyiqi/archive/2012/03/12/2391960.html

 

结论:正的权值的和-建图后的最小割的容量

 选择了一条边就会选择两个点,边的花费为正,点的花费为负,把边看成点,这个点向两个端点连一条边,表示选择这条边就会选择这两个点

然后题目就相当于最大权闭合图的模型了

题意:有n个点,m个选择,建造n个点各自需要一定花费,每个选择有一定的获利,会选择两个点,当然也要花费

求最大的获利

每个选择看成是获利点,每个点看成是花费点,新建源点向获利点建边,权值为获利的大小,花费点向汇点建边,权值为花费的大小

每个选择向相应的两个点连一条容量为无穷大的边,然后求网络的最小割

答案就为正的权值和-最小割的容量

最小割肯定为简单割(直接与源点或汇点相连),在这个题目中

如果与汇点相连的边为割边,表示这个点没有被选择来建station

如果与源点相连的边为割边,表示不选择某个客户的要求来连接某两个station

所以可以理解成:最终收益所有可能收益-(损失的收益+架设费用)括号中的即为最小割所求

View Code
#include<stdio.h>
#include<string.h>
const int MAX=60000;
const int INF=1000000000;
struct
{
int v,c,next;
}edge[1000000];
int E,head[MAX];
int gap[MAX],cur[MAX];
int pre[MAX],dis[MAX];
void add_edge(int s,int t,int c,int cc)//c,cc正向容量,反向容量
{}
int SAP(int s,int t,int n)//源点,汇点,总点数,返回最大流流量
{}
int main()
{
int n,m;
int a,b,c,i;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(head,-1,sizeof(head));
E=0;
for(i=1;i<=n;i++)
{
scanf("%d",&c);
add_edge(i,n+m+1,c,0);
}
int sum=0;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
sum+=c;
add_edge(0,i+n,c,0);
add_edge(i+n,a,INF,0);
add_edge(i+n,b,INF,0);
}
int ans=SAP(0,n+m+1,n+m+2);
printf("%d\n",sum-ans);
}
return 0;
}



 

你可能感兴趣的:(HDU)