TYVJ 1452 最大权闭合图

若有向图G的子图V满足【V中顶点的所有出边均指向V内部顶点】,则称V是G的一个闭合子图。其中点权和最大的闭合子图称为有向图G的最大权闭合子图,简称最大权闭合图。

最大权闭合图的构图方法如下:建立源点S和汇点T,源点S连所有点权为正的点,容量为该点点权;其余点连汇点T,容量为点权绝对值,对于原图中的边<u,v>,连边<u,v>,容量+∞。

定理1:最大权闭合图的点权和 = 所有正权点权值和 - 最小割(最大流)。

定理2:上述网络的最小割包含:S到“不在最大权闭合图内的正权节点”的边 以及 “在最大权闭合图内的负权节点”到T的边。

定理2的推论:在残余网络中由源点S能够访问到的点,就构成一个点数最少的最大权闭合图。

以上引自:lyd神犇的博客~http://hi.baidu.com/lydrainbowcat/item/ee01570b259f17cc75cd3c65

    以备自己复习时候看~

应用拓扑排序消环~ 

View Code
  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstdlib>
  4 #include <cstdio>
  5 #include <cstring>
  6 //先去环再去反向边,不能先建反边再去环 
  7 #define N 10010
  8 #define M 2000100
  9 #define INF 1e9
 10 
 11 using namespace std;
 12 
 13 int head[N],to[M],next[M],len[M];
 14 int pto[M],phead[N],pnext[M],pin[N],pout[N],val[N];
 15 int q[M*5],layer[N];
 16 bool vis[N];
 17 int n,cnt,pcnt,S,T,sum;
 18 
 19 inline void padd(int u,int v)
 20 {
 21     pto[pcnt]=v; pnext[pcnt]=phead[u]; phead[u]=pcnt++; 
 22     pin[v]++;
 23 }
 24 
 25 inline void add(int u,int v,int w)
 26 {
 27     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
 28     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
 29 }
 30 
 31 inline void topsort()
 32 {
 33     int h=1,t=1,sta;
 34     for(int i=1;i<=n;i++)
 35         if(pin[i]==0) q[t++]=i;
 36     while(h<t)
 37     {
 38         sta=q[h++];
 39         for(int i=phead[sta];~i;i=pnext[i])
 40         {
 41             pin[pto[i]]--;
 42             if(pin[pto[i]]==0) q[t++]=pto[i];
 43         }
 44     }
 45     for(int i=1;i<t;i++) vis[q[i]]=true;
 46 }
 47 
 48 inline void read()
 49 {
 50     memset(head,-1,sizeof head); cnt=0;
 51     memset(phead,-1,sizeof phead); pcnt=0;
 52     scanf("%d",&n);
 53     S=0; T=n+1;
 54     for(int i=1;i<=n;i++)
 55     {
 56         scanf("%d%d",&val[i],&pout[i]);
 57         for(int j=1,a;j<=pout[i];j++)
 58         {
 59             scanf("%d",&a);
 60             padd(a,i);
 61         }
 62     }
 63     topsort();
 64     for(int i=1;i<=n;i++)
 65         if(vis[i])
 66         {
 67             if(val[i]<0) add(i,T,-val[i]);
 68             else add(S,i,val[i]),sum+=val[i];
 69             for(int j=phead[i];~j;j=pnext[j])
 70                 if(vis[pto[j]]) add(pto[j],i,INF);
 71         }
 72 }
 73 
 74 inline bool bfs()
 75 {
 76     memset(layer,-1,sizeof layer);
 77     int h=1,t=2,sta;
 78     q[1]=S; layer[S]=0;
 79     while(h<t)
 80     {
 81         sta=q[h++];
 82         for(int i=head[sta];~i;i=next[i])
 83             if(len[i]&&layer[to[i]]<0)
 84             {
 85                 layer[to[i]]=layer[sta]+1;
 86                 q[t++]=to[i];
 87             }
 88     }
 89     return layer[T]!=-1;
 90 }
 91 
 92 inline int find(int u,int cur_flow)
 93 {
 94     if(u==T) return cur_flow;
 95     int res=0,tmp;
 96     for(int i=head[u];~i&&res<cur_flow;i=next[i])
 97         if(len[i]&&layer[to[i]]==layer[u]+1)
 98         {
 99             tmp=find(to[i],min(cur_flow-res,len[i]));
100             len[i]-=tmp; len[i^1]+=tmp; res+=tmp;
101         }
102     if(!res) layer[u]=-1;
103     return res;
104 }
105 
106 inline void go()
107 {
108     int ans=0;
109     while(bfs()) ans+=find(S,INF);
110     printf("%d\n",sum-ans);
111 } 
112 
113 int main()
114 {
115     read();
116     go();
117     return 0;
118 } 
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2848033.html