POJ-3204-Ikki's Story I - Road Reconstruction

来源:互联网 发布:万三蹄淘宝店哪家好吃 编辑:程序博客网 时间:2024/05/09 01:44

题目要求算出通过增加边的容量能够使得最大流增加的边数

思路:先用Dinic算出图的最大流,然后用DFS分别从始点和汇点进行搜索标记,最后枚举算出有多少点可以改变最大流即可

代码:

#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int maxn=501;const int maxm=200000;const int inf=1<<29;int n,m,e,st,des,head[maxn],pnt[maxm],nxt[maxm],cost[maxm],level[maxn],q[maxn];bool visa[maxn],visb[maxn];void AddEdge(int u,int v,int c){    pnt[e]=v;nxt[e]=head[u];cost[e]=c;head[u]=e++;    pnt[e]=u;nxt[e]=head[v];cost[e]=0;head[v]=e++;}bool BFS(){    memset(level,0,sizeof(level));    int pre=0,last=1;    q[pre]=st;    level[st]=1;    while(pre<last)    {if(q[pre]==des)    return true;for(int i=head[q[pre]];i!=-1;i=nxt[i])    if(cost[i]&&!level[pnt[i]])    {level[pnt[i]]=level[q[pre]]+1;q[last++]=pnt[i];    }pre++;    }    return false;}int DFS(int u,int sum){    if(u==des)return sum;    for(int i=head[u],t;i!=-1;i=nxt[i])if(cost[i]&&level[pnt[i]]==level[u]+1&&(t=DFS(pnt[i],min(sum,cost[i])))){    cost[i]-=t;    cost[i^1]+=t;    return t;}    return level[u]=0;}void DFSA(int u){    visa[u]=1;    for(int i=head[u];i!=-1;i=nxt[i])if(!visa[pnt[i]]&&cost[i])    DFSA(pnt[i]);}void DFSB(int u){    visb[u]=1;    for(int i=head[u];i!=-1;i=nxt[i])if(!visb[pnt[i]]&&cost[i^1])    DFSB(pnt[i]);}void Dinic(){    while(BFS())while(1){    int val=DFS(st,inf);    if(!val)break;}    memset(visa,0,sizeof(visa));    memset(visb,0,sizeof(visb));    DFSA(st);    DFSB(des);    int ans=0;    for(int i=0;i<e;i+=2)    {if(!cost[i]&&visa[pnt[i^1]]&&visb[pnt[i]])    ans++;    }    printf("%d\n",ans);}int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {st=e=0,des=n-1;memset(head,-1,sizeof(head));for(int i=0;i<m;i++){    int u,v,c;    scanf("%d%d%d",&u,&v,&c);    AddEdge(u,v,c);}Dinic();    }    return 0;}


原创粉丝点击