BZOJ1797 AHOI2009 Mincut最小割 网络流+连通性
题意:给定一张图,求每一条边:1、是否在一个最小割的方案里 2、是否在每一个最小割的方案里
题解:
先做最小割,然后在残余网络上缩点。对于一条边(u,v)
如果f[u]!=f[v],则(u,v)可以在某个最小割上(缩点后的图上的边均为满流边)
如果f[u]==f[S] && f[v]==f[T],则(u,v)在所有的最小割上(增大c(u,v)会导致最小割增大)
#include <stack> #include <queue> #include <vector> #include <cstdio> #include <cstring> #include <cstdlib> #include <climits> #include <iostream> #include <algorithm> using namespace std; const int MAXN=40000+2; const int MAXM=600000+2; struct EDGE{ int v,u,c; EDGE(){} EDGE(int _v,int _u,int _c):v(_v),u(_u),c(_c){} }e[2*MAXM]; int N,M,S,T,cnt,d[MAXN],f[MAXN],cur[MAXN],dfn[MAXN],low[MAXN],scc,depth; bool ans1[MAXN],ans2[MAXN],flag[MAXN]; queue<int> q; stack<int> s; vector<int> tab[MAXN]; void Insert(int u,int v,int c){ tab[u].push_back(cnt),e[cnt++]=EDGE(u,v,c); tab[v].push_back(cnt),e[cnt++]=EDGE(v,u,0); } bool BFS(int s,int t){ memset(d,-1,sizeof(d)); d[s]=0,q.push(s); int x; while(!q.empty()){ x=q.front(),q.pop(); for(int i=0;i<tab[x].size();i++) if(d[e[tab[x][i]].u]==-1 && e[tab[x][i]].c) d[e[tab[x][i]].u]=d[x]+1,q.push(e[tab[x][i]].u); } return d[t]>0; } int DFS(int x,int f,int t){ if(x==t) return f; int flow,used=0; for(int i=cur[x];i<tab[x].size();i++) if(e[tab[x][i]].c && d[e[tab[x][i]].u]==d[x]+1){ flow=DFS(e[tab[x][i]].u,min(f-used,e[tab[x][i]].c),t); e[tab[x][i]].c-=flow,e[tab[x][i]^1].c+=flow,used+=flow; if(e[tab[x][i]].c) cur[x]=i; if(f==used) return f; } if(!used) d[x]=-1; return used; } void Dinic(int s,int t){ while(BFS(s,t)){ memset(cur,0,sizeof(cur)); DFS(s,INT_MAX,t); } } void Tarjan(int x){ dfn[x]=low[x]=++depth,flag[x]=1,s.push(x); for(int i=0;i<tab[x].size();i++){ if(!e[tab[x][i]].c) continue; if(!dfn[e[tab[x][i]].u]) Tarjan(e[tab[x][i]].u),low[x]=min(low[x],low[e[tab[x][i]].u]); else if(flag[e[tab[x][i]].u]) low[x]=min(low[x],dfn[e[tab[x][i]].u]); } if(low[x]==dfn[x]){ int t=-1;scc++; while(t!=x){ t=s.top(),s.pop(),flag[t]=0; f[t]=scc; } } } int main(){ scanf("%d %d %d %d",&N,&M,&S,&T); for(int i=1,u,v,c;i<=M;i++){ scanf("%d %d %d",&u,&v,&c); Insert(u,v,c); } Dinic(S,T); for(int i=1;i<=N;i++) if(!dfn[i]) Tarjan(i); for(int i=0;i<cnt;i+=2){ if(e[i].c) puts("0 0"); else{ if(f[e[i].v]!=f[e[i].u]) printf("1 "); else printf("0 "); if(f[e[i].v]==f[S] && f[e[i].u]==f[T]) printf("1\n"); else printf("0\n"); } } return 0; }