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 } 

 

你可能感兴趣的:(T)