POJ 3204 最小割

题意:

在一个网络里面,问增大哪条边的容量可以使整个网络的流量增大,输出这种边个数。

题解:

显然这些边是最小割边集的子集。

对于边u-->v,当且仅当能从S沿着非满流的正向边遍历到u,从T沿着非满流的正向边遍历到v时,边u-->v是满足题意的边

两遍dfs求解~

 

View Code
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 
 7 #define N 1000
 8 #define M 500010
 9 #define INF 1e9
10 
11 using namespace std;
12 
13 int head[N],next[M],to[M],len[M];
14 int layer[N],q[M*10],vis[N];
15 int n,m,cnt,S,T;
16 
17 inline void add(int u,int v,int w)
18 {
19     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
20     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
21 }
22 
23 inline void read()
24 {
25     memset(head,-1,sizeof head); cnt=0;
26     scanf("%d%d",&n,&m);
27     S=1; T=n;
28     for(int i=1,a,b,c;i<=m;i++)
29     {
30         scanf("%d%d%d",&a,&b,&c); a++; b++;
31         add(a,b,c);
32     }
33 }
34 
35 inline bool bfs()
36 {
37     memset(layer,-1,sizeof layer);
38     int h=1,t=2,sta;
39     q[1]=S; layer[S]=0;
40     while(h<t)
41     {
42         sta=q[h++];
43         for(int i=head[sta];~i;i=next[i])
44             if(len[i]&&layer[to[i]]<0)
45             {
46                 layer[to[i]]=layer[sta]+1;
47                 q[t++]=to[i];
48             }
49     }
50     return layer[T]!=-1;
51 }
52 
53 inline int find(int u,int cur_flow)
54 {
55     if(u==T) return cur_flow;
56     int res=0,tmp;
57     for(int i=head[u];~i&&res<cur_flow;i=next[i])
58         if(len[i]&&layer[to[i]]==layer[u]+1)
59         {
60             tmp=find(to[i],min(cur_flow-res,len[i]));
61             len[i]-=tmp; len[i^1]+=tmp; res+=tmp;
62         }
63     if(!res) layer[u]=-1;
64     return res;
65 }
66 
67 inline void dfs1(int u)
68 {
69     vis[u]=1;
70     for(int i=head[u];~i;i=next[i])
71         if(vis[to[i]]==0&&len[i]>0) dfs1(to[i]);
72 }
73 
74 inline void dfs2(int u)
75 {
76     vis[u]=2;
77     for(int i=head[u];~i;i=next[i])
78         if(vis[to[i]]==0&&len[i^1]>0) dfs2(to[i]);
79 }
80 
81 inline void go()
82 {
83     int ans=0;
84     while(bfs()) ans+=find(S,INF);
85     dfs1(S); dfs2(T);
86     ans=0;
87     for(int i=0;i<cnt;i+=2)
88         if(vis[to[i]]==2&&vis[to[i^1]]==1) ans++;
89     printf("%d\n",ans);
90 }
91 
92 int main()
93 {
94     read();
95     go();
96     return 0;
97 }

 

 

posted @ 2013-01-08 21:44  proverbs  阅读(295)  评论(0编辑  收藏  举报