题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3061
题目大意:攻占每个城池有一定的收益(有正有负),且一个城池的占领要依赖另一些城池,求最大收益。
题目思路:经典题目,附出题人的解题报告:这是一个最小割的模型,具体的构图是:从源点连接正权的点,流量上限为该点的权值;从负权点连接汇点,流量上限为该点权值的绝对值;所有具有拓扑关系的点直接,从st连接end一条INF上限的边;求出最大流,最后用所有正权点的和减去最大流(最小割),便是答案。具体请参见07年的集训队论文《最小割模型在信息学竞赛中的应用》。
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<string> #include<queue> #include<algorithm> #include<vector> #include<stack> #include<list> #include<iostream> #include<map> #include<math.h> using namespace std; #define inf 0x3f3f3f3f #define Max 550 int max(int a,int b) { return a>b?a:b; } int min(int a,int b) { return a<b?a:b; } int dis[Max],gap[Max],pre[Max],cur[Max],p[Max]; int n,m,src,dest,eid; struct node { int to,next,c; }e[2*Max*Max]; void addedge(int u,int v,int c) { e[eid].to=v; e[eid].c=c; e[eid].next=p[u]; p[u]=eid++; } int ISAP(int st,int ed,int n) ///起点,终点,顶点数 { memset(dis, 0, sizeof(dis)); memset(gap, 0, sizeof(gap)); gap[0]=n; memcpy(cur, p, sizeof(p)); ///memcpy! int i,flag,v,u=pre[st]=st,maxflow=0,aug=inf; //puts("akk"); while(dis[st] < n) { for(flag=0,i=cur[u];i!=-1; i=e[i].next) /// cur[u] if(e[i].c&& dis[u] == dis[e[i].to]+1) { flag = 1; break; } if(flag) { if(aug > e[i].c) aug = e[i].c; v = e[i].to; pre[v] = u; cur[u] = i; u = v; if(u == ed) { for(u=pre[u]; 1;u=pre[u]) ///notice! { e[cur[u]].c -= aug; e[cur[u]^1].c += aug; if(u==st) break; // puts("akkk"); } maxflow += aug; aug = inf; } } else { int minx = n; for(i=p[u]; i!=-1; i=e[i].next) if(e[i].c&& dis[e[i].to]<minx) { minx = dis[e[i].to]; cur[u] = i; } if(--gap[dis[u]] == 0) break; dis[u] = minx+1; gap[dis[u]]++; u = pre[u]; } } // printf("Case %d:\n%d\n",count,maxflow); return maxflow; } int main() { int i,val,u,v; while(scanf("%d%d",&n,&m)!=EOF) { src=0; dest=n+1; eid=0; memset(p,-1,sizeof(p)); int sum=0; for(i=1;i<=n;i++) { scanf("%d",&val); if(val>0) { addedge(src,i,val); addedge(i,src,0); sum+=val; } else if(val<0) { addedge(i,dest,-val); addedge(dest,i,0); } } for(i=0;i<m;i++) { scanf("%d%d",&u,&v); addedge(u,v,inf); addedge(v,u,0); } printf("%d\n",sum-ISAP(src,dest,dest+1)); } }