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 }

 

posted @ 2018-03-25 21:38  CHerish_OI  阅读(160)  评论(0编辑  收藏  举报