题意:给定一个有向网络, 每条边均有一个容量。问是否存在一个从点1到点N,流量为C的流。如果不存在, 是否可以恰好修改一条弧饿容量, 使得存在这样的流。
先求最大流mf,如果mf >= C,则直接输出possible
若暂时不存在,那么便是最小割中的边限制了增广路的产生,可以通过修改其中的弧容量(设为C足矣),再求最大流,此时若大于C则此弧可以
不过这样会超时
其实最大流在此题中没有意义,所以当流量>=C的时候就可以停止增广了
还有就是保留第一次增广后的各条边中的流量,以后在此基础上进行增广即可
#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
//LOOP
#define FF(i, a, b) for(int i = (a); i < (b); ++i)
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FED(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
//STL
#define PB push_back
#define ALL(c) (c).begin(), (c).end()
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
//OUTPUT
#define WI(n) printf("%d\n", n)
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> VI;
const int INF = 100000000;
const double eps = 1e-10;
const int maxn = 110;
/////Dinic算法//////
struct Edge{
int from, to, cap, flow;
bool operator < (const Edge& e) const{
return (from < e.from || (from == e.from && to < e.to));
}
};
vector<Edge> edges;
VI G[maxn];
int n, m, s, t, C;
bool vis[maxn];
int d[maxn], cur[maxn];
void add(int from, int to, int cap)
{
edges.PB((Edge){from, to, cap, 0});
edges.PB((Edge){to, from, 0, 0});
int sz = edges.size();
G[from].PB(sz - 2);
G[to].PB(sz - 1);
}
bool bfs()
{
CLR(vis, 0);
queue<int> Q;
Q.push(s);
d[s] = 0;
vis[s] = 1;
while (!Q.empty())
{
int x = Q.front(); Q.pop();
REP(i, G[x].size())
{
Edge& e = edges[G[x][i]];
if (!vis[e.to] && e.cap > e.flow)
{
vis[e.to] = 1;
d[e.to] = d[x] + 1;
Q.push(e.to);
}
}
}
return vis[t];
}
int dfs(int x, int a)
{
if (x == t || a == 0) return a;
int flow = 0, f;
for (int& i = cur[x]; i < G[x].size(); i++)
{
Edge& e = edges[G[x][i]];
if (d[x] + 1 == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0)
{
e.flow += f;
edges[G[x][i] ^ 1].flow -= f;
flow += f;
a -= f;
if (a == 0) break;
}
}
return flow;
}
int maxflow()
{
int flow = 0;
while (bfs())
{
CLR(cur, 0);
flow += dfs(s, INF);
if (flow >= C)
break;
}
return flow;
}
void init()
{
FE(i, 0, n + 1)
G[i].clear();
edges.clear();
s = 1, t = n;
}
VI mincut;
VI last; // 保存第一次最大流中各边的流量,之后在此基础上增广
void solve()
{
int mf = maxflow();
if (mf >= C)
{
puts("possible");
return;
}
mincut.clear(), last.clear();
bfs();
m = edges.size();
REP(i, m)
{
int u = edges[i].from, v = edges[i].to, c = edges[i].cap;
if (vis[u] && !vis[v] && c > 0)
mincut.PB(i);
}
int sz = mincut.size();
vector<Edge> ans;
REP(j, m) last.PB(edges[j].flow);
REP(i, sz)
{
REP(j, m) edges[j].flow = last[j];
int oc = edges[mincut[i]].cap;
edges[mincut[i]].cap = C;
if (mf + maxflow() >= C) ans.PB(edges[mincut[i]]);
edges[mincut[i]].cap = oc;
}
sort(ALL(ans));
if (ans.size() > 0)
{
printf("possible option:");
REP(i, ans.size())
{
if (i) printf(",");
printf("(%d,%d)", ans[i].from, ans[i].to);
}
puts("");
}
else
puts("not possible");
}
int main()
{
int kase = 0;
while (~RIII(n, m, C), n || m || C)
{
int u, v, cap;
init();
REP(i, m)
{
RIII(u, v, cap);
add(u, v, cap);
}
printf("Case %d: ", ++kase);
solve();
}
return 0;
}