题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=33206
【思路】
最大流最小割。
可以确定的是如果不可行需要修改的是流量已经达到上限的最小割中的边。可以考虑依次修改求最大流。
优化:1 在原最大流的基础上增广; 2 只增广到流量C为止。
【代码】
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std; const int maxn = +;
const int INF = 1e9*+; struct Edge{
int u,v,cap,flow;
bool operator<(const Edge& rhs) const{
return u<rhs.u || (u==rhs.u && v<rhs.v) ;
}
};
struct Dinic {
int n,m,s,t;
bool vis[maxn];
int d[maxn],cur[maxn];
vector<int> G[maxn];
vector<Edge> es; void init(int n) {
this->n=n;
es.clear();
for(int i=;i<n;i++) G[i].clear();
}
void clearflow() {
for(int i=;i<es.size();i++) es[i].flow=;
}
void AddEdge(int u,int v,int cap) {
es.push_back((Edge){u,v,cap,});
es.push_back((Edge){v,u,,});
m=es.size();
G[u].push_back(m-);
G[v].push_back(m-);
} bool BFS() {
queue<int> q;
memset(vis,,sizeof(vis));
q.push(s); vis[s]=; d[s]=;
while(!q.empty()) {
int u=q.front(); q.pop();
for(int i=;i<G[u].size();i++) {
Edge& e=es[G[u][i]];
int v=e.v;
if(!vis[v] && e.cap>e.flow) {
vis[v]=;
d[v]=d[u]+;
q.push(v);
}
}
}
return vis[t];
}
int DFS(int u,int a) {
if(u==t || a==) return a;
int flow=,f;
for(int& i=cur[u];i<G[u].size();i++){
Edge& e=es[G[u][i]];
int v=e.v;
if( d[v]==d[u]+ && (f=DFS(v,min(a,e.cap-e.flow)))> ) {
e.flow+=f;
es[G[u][i]^].flow-=f;
flow+=f,a-=f;
if(!a) break;
}
}
return flow;
}
int Maxflow(int s,int t,int limit) {
this->s=s , this->t=t;
int flow=;
while(BFS() && flow<limit) {
memset(cur,,sizeof(cur));
flow+=DFS(s,INF);
}
return flow;
}
vector<int> Mincut() {
vector<int> ans;
for(int i=;i<es.size();i++)
if(es[i].cap!= && es[i].cap==es[i].flow)
ans.push_back(i);
return ans;
}
void reduce() {
for(int i=;i<es.size();i++) es[i].cap-=es[i].flow;
}
}dc; int n,m,C; int main() {
int kase=;
while(scanf("%d%d%d",&n,&m,&C)== && n) {
dc.init(n);
int u,v,w;
for(int i=;i<m;i++) {
scanf("%d%d%d",&u,&v,&w);
u--,v--;
dc.AddEdge(u,v,w);
}
int flow=dc.Maxflow(,n-,INF);
printf("Case %d: ",++kase);
if(flow>=C) printf("possible\n");
else {
vector<int> cut;
vector<Edge> ans;
cut=dc.Mincut();
dc.reduce(); //考虑除去最大流之后的剩余网络//即在原流基础上增广
for(int i=;i<cut.size();i++) {
dc.clearflow();
Edge& e=dc.es[cut[i]];
int tmp=e.cap;
e.cap=C;
if(flow+dc.Maxflow(,n-,C-flow)>=C) ans.push_back(e);
e.cap=tmp;
}
if(!ans.size()) printf("not possible\n");
else {
sort(ans.begin(),ans.end());
printf("possible option:");
int d=ans.size();
for(int i=;i<d-;i++) printf("(%d,%d),",ans[i].u+,ans[i].v+);
printf("(%d,%d)\n",ans[d-].u+,ans[d-].v+);
}
}
}
return ;
}