bzoj1797: [Ahoi2009]Mincut 最小割(最小割+强联通tarjan)
1797: [Ahoi2009]Mincut 最小割
题目:传送门
题解:
感觉是一道肥肠好的题目。
第二问其实比第一问简单?
用残余网络跑强联通,流量大于0才访问。
那么如果两个点所属的联通分量分别处于st和ed,那一定会被割掉,那么第一问就也会是1
但是第一问单独处理,就有点GG
膜了一发题解,发现贼尼玛niu bi:
还是利用联通分量,如果这条边满流,且连接的两个点所处的联通分量不同,就ok
太菜了不会证明...大佬hzwer
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #define inf 999999999 7 using namespace std; 8 typedef long long LL; 9 struct node 10 { 11 int x,y,next,other;LL c; 12 }a[2110000];int len,last[1110000]; 13 void ins(int x,int y,LL c) 14 { 15 int k1,k2; 16 k1=++len; 17 a[len].x=x;a[len].y=y;a[len].c=c; 18 a[len].next=last[x];last[x]=len; 19 20 k2=++len; 21 a[len].x=y;a[len].y=x;a[len].c=0; 22 a[len].next=last[y];last[y]=len; 23 24 a[k1].other=k2; 25 a[k2].other=k1; 26 } 27 int n,m,st,ed,head,tail; 28 int list[1110000],h[1110000]; 29 bool bt_h() 30 { 31 memset(h,0,sizeof(h));h[st]=1; 32 list[1]=st;head=1;tail=2; 33 while(head!=tail) 34 { 35 int x=list[head]; 36 for(int k=last[x];k;k=a[k].next) 37 { 38 int y=a[k].y; 39 if(h[y]==0 && a[k].c>0) 40 { 41 h[y]=h[x]+1; 42 list[tail++]=y; 43 } 44 } 45 head++; 46 } 47 if(h[ed]>0)return true; 48 return false; 49 } 50 LL find_flow(int x,LL flow) 51 { 52 if(x==ed)return flow; 53 LL s=0,t; 54 for(int k=last[x];k;k=a[k].next) 55 { 56 int y=a[k].y; 57 if(h[y]==h[x]+1 && a[k].c>0 && s<flow) 58 { 59 s+=t=find_flow(y,min(a[k].c,flow-s)); 60 a[k].c-=t;a[a[k].other].c+=t; 61 } 62 } 63 if(s==0)h[x]=0; 64 return s; 65 } 66 int low[1110000],dfn[1110000],belong[1110000],sta[1110000]; 67 int tp,id,cnt; 68 bool v[1110000]; 69 void dfs(int x) 70 { 71 low[x]=dfn[x]=++id; 72 sta[++tp]=x;v[x]=true; 73 for(int k=last[x];k;k=a[k].next) 74 { 75 int y=a[k].y; 76 if(a[k].c!=0) 77 { 78 if(dfn[y]==-1) 79 { 80 dfs(y); 81 low[x]=min(low[x],low[y]); 82 } 83 else 84 if(v[y]==true) 85 low[x]=min(low[x],dfn[y]); 86 } 87 } 88 if(low[x]==dfn[x]) 89 { 90 int i;cnt++; 91 do{ 92 i=sta[tp--]; 93 v[i]=false; 94 belong[i]=cnt; 95 }while(i!=x); 96 } 97 } 98 int main() 99 { 100 scanf("%d%d%d%d",&n,&m,&st,&ed); 101 len=0;memset(last,0,sizeof(last)); 102 for(int i=1;i<=m;i++) 103 { 104 int x,y;LL c; 105 scanf("%d%d%lld",&x,&y,&c); 106 ins(x,y,c); 107 } 108 LL ans=0; 109 while(bt_h())ans+=find_flow(st,inf); 110 memset(sta,0,sizeof(sta)); 111 memset(dfn,-1,sizeof(dfn)); 112 memset(low,0,sizeof(low)); 113 memset(v,false,sizeof(v)); 114 id=tp=cnt=0; 115 for(int i=1;i<=n;i++) 116 if(dfn[i]==-1) 117 dfs(i); 118 for(int i=1;i<len;i+=2) 119 { 120 int x=a[i].x,y=a[i].y; 121 if(a[i].c!=0){printf("0 0\n");continue;} 122 if(belong[x]!=belong[y])printf("1 "); 123 else printf("0 "); 124 if((belong[x]==belong[st] && belong[y]==belong[ed])) 125 printf("1\n"); 126 else printf("0\n"); 127 } 128 return 0; 129 }