大白书上面网络流的一道题,第一次接触这种保存残余网络流,然后直接在此基础之上进行更新,不过这个题我写的时候需要注意的地方就是最后找最小割后,进行不断枚举一个割边更新的时候一定要是原来的输入的边,而不是我们添加的反向边,在这里WA了1个多小时。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<algorithm> using namespace std; const int inf=2000000100; const int maxn=200; const int maxm=1e5; int n,m,c,st,des,cnt,e,head[maxn],nxt[maxm],pnt[maxm],from[maxm],flow[maxm],cap[maxm],level[maxn]; bool vis[maxn]; queue<int> q; struct Node { int from; int to; Node(){}; Node(int sfrom,int sto) { from=sfrom; to=sto; } bool operator < (const Node &a)const { if(from==a.from) return to<a.to; return from<a.from; } }ans[maxm]; void AddEdge(int u,int v,int f) { pnt[e]=v;from[e]=u;nxt[e]=head[u];cap[e]=f;head[u]=e++; pnt[e]=u;from[e]=v;nxt[e]=head[v];cap[e]=0;head[v]=e++; } bool BFS() { memset(level,0,sizeof(level)); level[st]=1; q.push(st); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=nxt[i]) if(cap[i]&&!level[pnt[i]]) { level[pnt[i]]=level[u]+1; q.push(pnt[i]); } } return level[des]; } bool bfs() { memset(level,0,sizeof(level)); level[st]=1; q.push(st); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=nxt[i]) if(cap[i]>flow[i]&&!level[pnt[i]]) { level[pnt[i]]=level[u]+1; q.push(pnt[i]); } } return level[des]; } int DFS(int u,int maxf) { if(u==des||!maxf) return maxf; for(int i=head[u],t;i!=-1;i=nxt[i]) if(level[pnt[i]]==level[u]+1&&(t=DFS(pnt[i],min(maxf,cap[i])))) { cap[i]-=t; cap[i^1]+=t; return t; } return level[u]=0; } int dfs(int u,int maxf) { if(u==des||!maxf) return maxf; for(int i=head[u],t;i!=-1;i=nxt[i]) if(level[pnt[i]]==level[u]+1&&(t=dfs(pnt[i],min(maxf,cap[i]-flow[i])))) { flow[i]+=t; flow[i^1]-=t; return t; } return level[u]=0; } int maxflow() { int ans=0; while(BFS()) while(1) { int val=DFS(st,inf); if(!val) break; ans+=val; } return ans; } int maxflow2(int flow) { int ans=0; while(bfs()) while(1) { int val=dfs(st,inf); if(!val) break; ans+=val; if(flow+ans>=c) return ans; } return ans; } void GetMinCut(int u) { vis[u]=1; for(int i=head[u];i!=-1;i=nxt[i]) if(!vis[pnt[i]]&&cap[i]) GetMinCut(pnt[i]); } void ClearFlow() { memset(flow,0,sizeof(flow)); } void Solve() { int flow=maxflow(); if(flow>=c) { printf("possible\n"); return; } cnt=0; GetMinCut(st); for(int i=0;i<e;i+=2) if(vis[from[i]]&&!vis[pnt[i]]) { // printf("Update %d %d %d\n",from[i],pnt[i],cap[i]); cap[i]=c; ClearFlow(); int val=maxflow2(flow); if(val+flow>=c) ans[cnt++]=Node(from[i],pnt[i]); cap[i]=0; } if(!cnt) { printf("not possible\n"); return; } sort(ans,ans+cnt); printf("possible option:"); printf("(%d,%d)",ans[0].from,ans[0].to); for(int i=1;i<cnt;i++) printf(",(%d,%d)",ans[i].from,ans[i].to); printf("\n"); } int main() { int cas=1; while(scanf("%d%d%d",&n,&m,&c)&&(n+m+c)) { memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); e=0; st=1,des=n; for(int i=0;i<m;i++) { int u,v,f; scanf("%d%d%d",&u,&v,&f); AddEdge(u,v,f); } printf("Case %d: ",cas++); if(n==1) { printf("possible\n"); continue; } Solve(); } return 0; }