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 }
没有人能阻止我前进的步伐,除了我自己!