bzoj 1797 mincut
有点偏向结论性质的题。
最小割是把图分成S和T两个互不联通的部分,切割的总容量的小小值。
论文里说过,在最小割里的边一定是满流边但漫流边不一定是最小割里的边。
有了这两个性质,我们可以这么想,如果这个边的两端同在S或T里的话一定不成立。于是,我们在残量图里跑tarjan,一定可以得到被切割后的几个联通块,如果两个点在同一个联通分量里,那么这条边一定不是最小割边。
如果这条边分别联通S,T这两个联通分量,并且满流的话,那么这条一定是最小割的边。
解释的不是很清楚,总之最重要的是对最小割的理解。
mincut
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #define maxn 10000 7 #define maxm 420000 8 #define inf 2147483647 9 using namespace std; 10 11 struct et 12 { 13 int s,t,val,next; 14 } 15 e[maxm]; 16 int dis[maxn],gap[maxn],fir[maxn],web[maxn],q[maxn],last[maxn],dfn[maxn],low[maxn],v[maxn]; 17 int n,m,num,tot,st,ed,tim,tail,sum; 18 19 int dfs(int now,int flow) 20 { 21 int sap=0; 22 if (now==ed) return flow; 23 for (int j=last[now]; j ;j=e[j].next) 24 { 25 int k=e[j].t; 26 if ((e[j].val)&&(dis[now]==dis[k]+1)) 27 { 28 last[now]=j; 29 int tmp=dfs(k,min(e[j].val,flow-sap)); 30 e[j].val-=tmp; 31 e[j^1].val+=tmp; 32 sap+=tmp; 33 if (sap==flow) return sap; 34 } 35 } 36 if (dis[st]>=num) return sap; 37 if (!(--gap[dis[now]])) dis[st]=num; 38 ++gap[++dis[now]]; 39 last[now]=fir[now]; 40 return sap; 41 } 42 43 void tarjan(int i) 44 { 45 dfn[i]=low[i]=++tim; 46 q[++tail]=i; 47 v[i]=1; 48 for (int j=fir[i];j;j=e[j].next) 49 if (e[j].val) 50 { 51 int k=e[j].t; 52 if (!v[k]) tarjan(k); 53 if (v[k]<2) low[i]=min(low[i],low[k]); 54 } 55 if (dfn[i]==low[i]) 56 { 57 ++sum; 58 while (q[tail+1]!=i) 59 { 60 web[q[tail]]=sum; 61 v[q[tail]]=2; 62 --tail; 63 } 64 } 65 } 66 67 void add(int x,int y,int z) 68 { 69 e[++tot].s=x;e[tot].t=y;e[tot].val=z;e[tot].next=fir[x];fir[x]=tot; 70 e[++tot].s=y;e[tot].t=x;e[tot].val=0;e[tot].next=fir[y];fir[y]=tot; 71 } 72 73 int main() 74 { 75 scanf("%d %d %d %d",&n,&m,&st,&ed); 76 num=n; tot=1; 77 int x,y,z; 78 for (int i=1;i<=m;i++) 79 { 80 scanf("%d %d %d",&x,&y,&z); 81 add(x,y,z); 82 } 83 memset(dis,0,sizeof(dis)); 84 memset(gap,0,sizeof(gap)); 85 gap[0]=num; 86 for (int i=1;i<=n;i++) last[i]=fir[i]; 87 int ans=0; 88 while (dis[st]<num) ans+=dfs(st,inf); 89 memset(v,0,sizeof(v)); 90 for (int i=1;i<=n;i++) web[i]=i; 91 sum=n; 92 for (int i=1;i<=n;i++) 93 if (!v[i]) tarjan(i); 94 //for (int i=1;i<=n;i++) cout<<web[i]<<endl; 95 for (int i=1;i<=m;i++) 96 { 97 int j=i*2; 98 x=e[j].s; y=e[j].t; 99 ans=0; 100 if ((web[x]!=web[y])&&(!e[j].val)) 101 { 102 ans=1; 103 if ((web[x]==web[st])&&(web[y]==web[ed])) 104 ans=2; 105 } 106 if (ans==0) printf("0 0\n"); 107 else 108 if (ans==1) printf("1 0\n"); 109 else 110 if (ans==2) printf("1 1\n"); 111 } 112 return 0; 113 } 114
AC without art, no better than WA !