#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back const int maxn=2e5+7; const int inf=0x3f3f3f3f; int num_nodes,num_edges; int tot; int d[maxn],cur[maxn],source,sink; int p[maxn],num[maxn],vis[maxn]; struct EDGE{ int from,to,cap,flow; }; vector<EDGE>edge; vector<int>G[maxn]; void init(){ edge.clear(); for(int i=0;i<maxn;i++)G[i].clear(); } void addedge(int u,int v,int w){ edge.push_back((EDGE){u,v,w,0}); edge.push_back((EDGE){v,u,0,0}); tot=edge.size(); G[u].push_back(tot-2); G[v].push_back(tot-1); } int bfs(){ memset(vis,0,sizeof vis); queue<int>Q; Q.push(sink); vis[sink]=1; d[sink]=0; while(!Q.empty()){ int u=Q.front(); Q.pop(); int sz=G[u].size(); for(int i=0;i<sz;++i){ EDGE &e=edge[G[u][i]^1]; if(!vis[e.from] && e.cap>e.flow){ vis[e.from]=1; d[e.from]=d[u]+1; Q.push(e.from); } } } return vis[source]; } int augment(){ int u=sink,a=inf; while(u!=source){ EDGE &e=edge[p[u]]; a=min(a,e.cap-e.flow); u=edge[p[u]].from; } u=sink; while(u!=source){ edge[p[u]].flow+=a; edge[p[u]^1].flow-=a; u=edge[p[u]].from; } return a; } int maxflow(){ int flow=0; bfs(); memset(num,0,sizeof num); for(int i=0;i<=num_nodes;i++)num[d[i]]++; int u=source; memset(cur,0,sizeof cur); while(d[source]<num_nodes){ if(u==sink){ flow+=augment(); u=source; } int advance=0; int sz=G[u].size(); for(int i=cur[u];i<sz;i++){ EDGE &e=edge[G[u][i]]; if(e.cap>e.flow && d[u]==d[e.to]+1){ advance=1; p[e.to]=G[u][i]; cur[u]=i; u=e.to; break; } } if(!advance){ int m=num_nodes-1; int sz=G[u].size(); for(int i=0;i<sz;i++){ if(edge[G[u][i]].cap>edge[G[u][i]].flow){ m=min(m,d[edge[G[u][i]].to]); } } if(--num[d[u]]==0)break; num[d[u]=m+1]++; cur[u]=0; if(u!=source)u=edge[p[u]].from; } } return flow; } vector<int>cut; void mincut(){ bfs();cut.clear(); int sz=edge.size(); for(int i=0;i<sz;i++){ EDGE &e=edge[i]; if(vis[e.to]&&!vis[e.from]&&e.cap>0)cut.pb(i); } } void reduce(){ //上限缩减,不重复统计原始最大流 int sz=edge.size(); for(int i=0;i<sz;i++)edge[i].cap-=edge[i].flow; } void flowclear(){ int sz=edge.size(); for(int i=0;i<sz;i++)edge[i].flow=0; } int cmp(EDGE a,EDGE b){ if(a.from==b.from)return a.to<b.to; else return a.from<b.from; } int main(){ int kase=0;int n,m,c; while(scanf("%d%d%d",&n,&m,&c)&&n){ num_nodes=n; source=1;sink=n; init(); for(int i=1;i<=m;i++){ int u,v,w;scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); } printf("Case %d: ",++kase); int maxFlow=maxflow(); if(maxFlow>=c||c==0)printf("possible "); else{ vector<EDGE>ans; mincut(); reduce();int sz=cut.size(); for(int i=0;i<sz;i++){ flowclear(); EDGE &e=edge[cut[i]]; e.cap+=c; if(maxFlow+maxflow()>=c)ans.pb(edge[cut[i]]); e.cap-=c; } if(ans.empty())printf("not possible "); else{ sort(ans.begin(),ans.end(),cmp); int sz=ans.size(); for(int i=0;i<sz;i++){ if(i==0)printf("possible option:(%d,%d)",ans[i].from,ans[i].to); else printf(",(%d,%d)",ans[i].from,ans[i].to); } printf(" "); } } } }
要点在于reduce函数的上限缩减
算是最小割的模板