bzoj 1797: [Ahoi2009]Mincut 最小割

来源:互联网 发布:儿童听故事软件 编辑:程序博客网 时间:2024/06/03 19:23

是又是一道好题啊!

首先,我觉得可以很容易可以想到一个O(m)的复杂度,但对于这一题,每条边都跑一次肯定是不现实的做法。。
然后我就不会了

于是去看题解。。发现居然有结论。。
我就把结论总结一下吧

结论1(用于解决第一问):

对于一条边,要是有一种割集包含他的话,那么他肯定是满流的。但如果他是漫流的,不一定有一个割集包含他。

证明:
我们先证明:如果一条边不是满流的,那么肯定没有割集包含他。这个的话应该挺好懂的,假如他没有满流,那么肯定是后面有一条或若干条边限制了他,那么我们只需要割掉限制他的东西,并不需要割掉它。。
由此得出,第一句话是对的
第二句我们可以举反例,这个随手画画就好了。。

但这一个结论并不可以解决第一问,我们还需要第二个

结论2(用于解决第一问):

如果一条边的两端x和y,在残余网络中属于同一个连通分量,那么也没有一个割集包含他

证明:
这个也很容易啊!这不就说明后面还是有东西在限制他嘛。。

于是第一问就解决了。。

结论3(用于解决第二问):

满流的桥是一定要割的。。

证明:不用了吧

于是这题就做完了

#include<cstdio>#include<queue>#include<algorithm>#include<cstring>#include<iostream>using namespace std;const int N=4005;const int M=60005*2;struct qq{    int x,y,z,last;}s[M];int num,last[N];int n,m,S,T;void init (int x,int y,int z){    num++;    s[num].x=x;s[num].y=y;s[num].z=z;    s[num].last=last[x];    last[x]=num;}int h[N];bool bt (){    memset(h,-1,sizeof(h));h[S]=1;    queue<int> q;    q.push(S);    while (!q.empty())    {        int x=q.front();q.pop();        for (int u=last[x];u!=-1;u=s[u].last)        {            int y=s[u].y;            if (s[u].z>0&&h[y]==-1)            {                h[y]=h[x]+1;                q.push(y);            }        }    }    return h[T]!=-1;}int mymin (int x,int y){return x<y?x:y;}int dfs (int x,int f){    if (x==T) return f;    int s1=0;    for (int u=last[x];u!=-1;u=s[u].last)    {        int y=s[u].y;        if (s[u].z>0&&h[y]==h[x]+1&&s1<f)        {            int lalal=dfs(y,mymin(s[u].z,f-s1));            s1+=lalal;            s[u].z-=lalal;            s[u^1].z+=lalal;        }    }    if (s1==0) h[x]=-1;    return s1;}int dfn[N],low[N],belong[N],cnt,sta[N],lalal,shen;bool in[N];void dfs1 (int x){    dfn[x]=low[x]=++lalal;    sta[++cnt]=x;    in[x]=true;    for (int u=last[x];u!=-1;u=s[u].last)    {        if (s[u].z>0)        {            int y=s[u].y;            if (dfn[y]==-1)            {                dfs1(y);                low[x]=mymin(low[x],low[y]);            }            else if (in[y]) low[x]=mymin(dfn[y],low[x]);        }    }    if (low[x]==dfn[x])    {        shen++;        int now;        do        {            now=sta[cnt--];            belong[now]=shen;            in[now]=false;        }while (now!=x);    }}int main(){    num=1;memset(last,-1,sizeof(last));    scanf("%d%d%d%d",&n,&m,&S,&T);    for (int u=1;u<=m;u++)    {        int x,y,z;        scanf("%d%d%d",&x,&y,&z);        init(x,y,z);init(y,x,0);    }    int ans=0;    while (bt()) ans=ans+dfs(S,1<<30);    shen=lalal=cnt=0;    memset(dfn,-1,sizeof(dfn));    memset(in,false,sizeof(in));    for (int u=1;u<=n;u++)        if (dfn[u]==-1)            dfs1(u);    //for (int u=1;u<=n;u++) printf("%d ",belong[u]);    for (int u=2;u<=m*2;u+=2)    {        if (s[u].z!=0) printf("0 0\n");        else        {            if (belong[s[u].x]!=belong[s[u].y]) printf("1 ");            else printf("0 ");            if ((belong[s[u].x]==belong[S])&&(belong[s[u].y]==belong[T])) printf("1\n");            else printf("0\n");        }    }    return 0;}
原创粉丝点击