坑爹啊 c可能为0......又是两小时
先求出最大流 然后可能修改的边只能是最小割的边, 枚举没条边
保存修改之前的最大流 每次枚举时不重新找最大流直接在初始最大流上跑
只要最大流超过c就可以停止了
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long ll;
const int MAXN = 107;
const ll INF = 1LL << 51;
struct Dinic {
struct Edge {
int from, to, flow;
ll cap;
Edge() {};
Edge(int from, int to, ll cap, int flow):from(from), to(to), cap(cap), flow(flow) {}
bool operator < (const Edge &e) const {
return from < e.from || from == e.from && to < e.to;
}
};
vector<Edge> edges, estmp;
vector<int> G[MAXN];
vector<int> cut;
Edge able[MAXN*MAXN*2];
int d[MAXN], cur[MAXN];
int n, m, s, t;
int nable;
ll c, flow;
bool vis[MAXN];
void init(int n, ll c, int s, int t) {
this->n = n, this->c = c, this->s = s, this->t = t;
for(int i = 1; i <= n; i++) G[i].clear();
edges.clear();
flow = 0;
}
void addedge(int u, int v, ll cap) {
edges.push_back( Edge(u, v, cap, 0));
edges.push_back( Edge(v, u, 0, 0));
m = edges.size();
G[u].push_back(m - 2);
G[v].push_back(m - 1);
}
bool bfs() {
memset(vis, 0, sizeof(vis));
memset(d, -1, sizeof(d));
queue<int> q;
q.push(s);
d[s] = 0;
vis[s] = true;
while( !q.empty()) {
int u = q.front(); q.pop();
int i, sz = G[u].size();
for(i = 0; i < sz; i++) {
Edge e = edges[ G[u][i]];
if( !vis[e.to] && e.cap > e.flow) {
vis[e.to] = true;
d[e.to] = d[u] + 1;
q.push(e.to);
}
}
}
return vis[t];
}
ll dfs(int u, ll limit) {
if(u == t || limit == 0) return limit;
int flow = 0, f, sz = G[u].size();
for(int &i = cur[u]; i < sz; i++) {
Edge &e = edges[ G[u][i]];
if(d[u] + 1 == d[e.to] && (f = dfs(e.to, min(limit, e.cap - e.flow) ) ) > 0) {
e.flow += f;
edges[ G[u][i] ^ 1].flow -= f;
flow += f;
limit -= f;
if(limit == 0) break;
}
}
return flow;
}
bool Maxflow() {
while( bfs()) {
memset(cur, 0, sizeof(cur));
flow += dfs(s, INF);
if(flow >= c) return true;
}
return false;
}
void getcut() {
cut.clear();
int i, sz = edges.size();
for(i = 0; i < sz; i += 2) {
if(vis[ edges[i].from] && !vis[ edges[i].to]) {
cut.push_back(i);
}
}
}
void getable() {
getcut();
nable = 0;
estmp.clear();
int i, sz = edges.size();
for(i = 0; i <sz; i++) estmp.push_back(edges[i]);
ll lastflow = flow;
sz = cut.size();
for(i = 0; i < sz; i++) {
edges[cut[i]].cap = edges[cut[i]].flow + c;
if(Maxflow()) able[nable++] = edges[cut[i]];
flow = lastflow;
int j, csz = estmp.size();
edges.clear();
for(j = 0; j < csz; j++) edges.push_back(estmp[j]);
}
}
}Dic;
int main() {
int n, e, id = 0;
ll c, cap;
while(~scanf("%d%d%lld", &n, &e, &c), n|e|c) {
if(c < 0) while(1);
Dic.init(n, c, 1, n);
int i, u, v;
for(i = 1; i <= e; i++) {
scanf("%d%d%lld", &u, &v, &cap);
Dic.addedge(u, v, cap);
}
printf("Case %d: ", ++id);
if(Dic.Maxflow() || c == 0) puts("possible");
else {
Dic.getable();
if(Dic.nable <= 0) puts("not possible");
else {
sort(Dic.able, Dic.able + Dic.nable);
printf("possible option:(%d,%d)", Dic.able[0].from, Dic.able[0].to);
for(i = 1; i < Dic.nable; i++)
printf(",(%d,%d)", Dic.able[i].from, Dic.able[i].to);
puts("");
}
}
}
return 0;
}