POJ 2987 Firing 网络流 最大权闭合图
http://poj.org/problem?id=2987
https://blog.csdn.net/u014686462/article/details/48533253
给一个闭合图,要求输出其最大权闭合图的权值和需要选的最少点数,最大权闭合图定义和网络流连边方式见博客。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<iostream> 6 #include<queue> 7 using namespace std; 8 #define LL long long 9 const int maxn=10010; 10 const LL minf=(LL)1e14; 11 int n,m,s,t; 12 LL val[maxn]={}; 13 struct nod{ 14 int y,next;LL v; 15 }e[maxn*20]; 16 int head[maxn],tot=1; 17 queue<int>q; 18 int dep[maxn]={},vis[maxn]={},id[maxn]={},tai=0; 19 void init(int x,int y,LL v){ 20 e[++tot].y=y;e[tot].v=v;e[tot].next=head[x];head[x]=tot; 21 } 22 bool dfs(){ 23 memset(dep,0,sizeof(dep)); 24 q.push(s);dep[s]=1; 25 while(!q.empty()){ 26 int x=q.front();q.pop(); 27 for(int i=head[x];i;i=e[i].next){ 28 if(e[i].v&&!dep[e[i].y]){ 29 dep[e[i].y]=dep[x]+1; 30 q.push(e[i].y); 31 } 32 } 33 } 34 return dep[t]; 35 } 36 LL dfs1(int x,LL fc){ 37 if(x==t){ 38 return fc; 39 } 40 LL he=0,z; 41 for(int i=head[x];i;i=e[i].next){ 42 if(dep[x]+1==dep[e[i].y]){ 43 z=dfs1(e[i].y,min(fc-he,e[i].v)); 44 he+=z;e[i].v-=z;e[i^1].v+=z; 45 if(he==fc)break; 46 } 47 } 48 return he; 49 } 50 void dfs2(int x){ 51 if(x==t)return; 52 if(x!=s)id[++tai]=x; 53 vis[x]=1; 54 for(int i=head[x];i;i=e[i].next){ 55 if(e[i].v&&!vis[e[i].y]){ 56 dfs2(e[i].y); 57 } 58 } 59 } 60 int main(){ 61 int x,y; LL ans=0; 62 scanf("%d%d",&n,&m); 63 s=n+1;t=s+1; 64 for(int i=1;i<=n;i++){ 65 scanf("%lld",&val[i]); 66 if(val[i]>=0){init(s,i,val[i]);init(i,s,0);ans=ans+val[i];} 67 else {init(i,t,-val[i]);init(t,i,0);} 68 } 69 for(int i=1;i<=m;i++){ 70 scanf("%d%d",&x,&y); 71 init(x,y,minf);init(y,x,0); 72 } 73 while(dfs())ans-=dfs1(s,minf); 74 dfs2(s); 75 printf("%d ",tai); 76 printf("%lld\n",ans); 77 return 0; 78 }