poj 3204 最大流

来源:互联网 发布:杜应流 知乎 编辑:程序博客网 时间:2024/06/05 06:08

传送门

题意:给你一个有向图,货物从0流向n-1,问哪些边扩增了流量能使总流量增加,输出边数。

思路:先最大流求一遍,在从0点dfs找出剩余流量能流到的点,再从n-1点dfs,找出剩余流量能流到n-1的点,然后前面的点和后面的点一一枚举,如果这两点原本有边并且流量已满,那就说明扩增它能使总流量增加,找到这样的点的对数即是答案。

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#define maxn 1<<30using namespace std;int f[10005],c[10005],pre[505],lu[505];int fst[505],next[10005],node[10005];int n,m,en,snum,tnum,fr[505],be[505],ff[505][505],cc[505][505];bool vis[505];bool bfs(int s,int t){    memset(vis,0,sizeof(vis));    queue<int>q;    q.push(s);    vis[s]=1;    while(!q.empty())    {        int u=q.front();        q.pop();        for(int i=fst[u];i!=-1;i=next[i])        {            int v=node[i];            if(c[i]>f[i]&&!vis[v])            {                lu[v]=i;                pre[v]=u;                vis[v]=1;                if(v==t)return true;                q.push(v);            }        }    }    return false;}void EK(int s,int t){    while(bfs(s,t))    {        int mi=maxn;        for(int i=t;i!=s;i=pre[i])        {            int r=lu[i];            if(mi>c[r]-f[r])mi=c[r]-f[r];        }        for(int i=t;i!=s;i=pre[i])        {            int r=lu[i];            f[r]+=mi;            f[r^1]-=mi;            ff[pre[i]][i]+=mi;            ff[i][pre[i]]-=mi;        }    }}void dfs1(int u){    fr[snum++]=u;    vis[u]=1;    for(int i=fst[u];i!=-1;i=next[i])    {        int v=node[i];        if(!vis[v]&&c[i]>f[i])dfs1(v);    }}void dfs2(int u){    be[tnum++]=u;    vis[u]=1;    for(int i=fst[u];i!=-1;i=next[i])    {        int v=node[i];        if(!vis[v]&&c[i^1]>f[i^1])dfs2(v);    }}int main(){    int u,v,va;    en=0;    memset(fst,-1,sizeof(fst));    memset(f,0,sizeof(f));    memset(cc,0,sizeof(cc));    memset(ff,0,sizeof(ff));    scanf("%d%d",&n,&m);    for(int i=0;i<m;i++)    {        scanf("%d%d%d",&u,&v,&va);        next[en]=fst[u];        fst[u]=en;        node[en]=v;        c[en]=va;        cc[u][v]=va;        en++;        next[en]=fst[v];        fst[v]=en;        node[en]=u;        c[en]=0;        en++;    }    EK(0,n-1);    snum=0;    tnum=0;    memset(vis,0,sizeof(vis));    dfs1(0);    memset(vis,0,sizeof(vis));    dfs2(n-1);    int ans=0;    for(int i=0;i<snum;i++)    {        for(int j=0;j<tnum;j++)        {            u=fr[i];            v=be[j];            if(cc[u][v]&&cc[u][v]==ff[u][v])ans++;        }    }    printf("%d\n",ans);    return 0;}


原创粉丝点击