大白书上面网络流的一道题,第一次接触这种保存残余网络流,然后直接在此基础之上进行更新,不过这个题我写的时候需要注意的地方就是最后找最小割后,进行不断枚举一个割边更新的时候一定要是原来的输入的边,而不是我们添加的反向边,在这里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;
}