有n个城市和m个中转点,0号点是汇点。问提高哪一条边的容量可以使进入汇点的容量增加。
如果一条边对总的流量有影响,那么它在求完最大流的残余网络中肯定满足两个条件:第一,这条边是满流;第二,源点和汇点分别经过未满流的边可达此边的两个端点。
因此就是求最大流后在残余网络中dfs处理一下连通性,然后遍历每一条边判断即可。
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 205;
const int maxm = 100050;
const int INF = 0x3f3f3f3f;
int n, m, k, a, b, x, no, head[maxn], q[maxm];
int sta[maxn], gap[maxn], cur[maxn], level[maxn];
bool vis[maxn][2];
vector<int>ans;
struct node
{
int from, to, nxt, id;
int cap, flow;
}e[maxm];
void add(int u, int v, int w, int id)
{
e[no].from = u, e[no].to = v, e[no].nxt = head[u];
e[no].cap = w, e[no].flow = 0, e[no].id = id;
head[u] = no++;
e[no].from = v, e[no].to = u, e[no].nxt = head[v];
e[no].cap = 0, e[no].flow = 0, e[no].id = id;
head[v] = no++;
}
void bfs(int s, int t)
{
int fro = 0, rea = 0;
memset(level, -1, sizeof(level));
memset(gap, 0, sizeof(gap));
gap[0] = 1;
level[t] = 0;
q[rea++] = t;
while(fro != rea)
{
int u = q[fro++];
for(int i = head[u];i != -1;i = e[i].nxt)
{
int v = e[i].to;
if(level[v] == -1)
{
level[v] = level[u] + 1;
gap[level[v]]++;
q[rea++] = v;
}
}
}
}
int sap(int s, int t, int N)
{
bfs(s, t);
memcpy(cur, head, sizeof(head));
int top = 0, u = s, ans = 0;
while(level[s] < N)
{
if(u == t)
{
int minn = INF; int id;
for(int i = 0;i < top;i++)
{
if(minn > e[sta[i]].cap - e[sta[i]].flow)
{
minn = e[sta[i]].cap - e[sta[i]].flow;
id = i;
}
}
for(int i = 0;i < top;i++)
{
e[sta[i]].flow += minn;
e[sta[i]^1].flow -= minn;
}
ans += minn, top = id;
u = e[sta[top]^1].to;
continue;
}
bool flag = 0; int v;
for(int i = cur[u];i != -1;i = e[i].nxt)
{
v = e[i].to;
if(e[i].cap - e[i].flow && level[v] + 1 == level[u])
{
flag = 1;
cur[u] = i;
break;
}
}
if(flag)
{
sta[top++] = cur[u];
u = v;
continue;
}
int minn = N;
for(int i = head[u];i != -1;i = e[i].nxt)
{
if(e[i].cap - e[i].flow && minn > level[e[i].to])
{
minn = level[e[i].to];
cur[u] = i;
}
}
gap[level[u]]--;
if(!gap[level[u]]) return ans;
level[u] = minn + 1;
gap[level[u]]++;
if(u != s) u = e[sta[--top]^1].to;
}
return ans;
}
void dfs(int u, int op)
{
vis[u][op] = 1;
for(int i = head[u];i != -1;i = e[i].nxt)
{
int v = e[i].to;
if(op == 0)
{
if(e[i].cap - e[i].flow && !vis[v][op])
dfs(v, op);
}
else
{
if(e[i^1].cap - e[i^1].flow && !vis[v][op])
dfs(v, op);
}
}
}
int main()
{
while(scanf("%d%d%d", &n, &m, &k))
{
if(n == 0 && m == 0 && k == 0) break;
int s = n + m + 1, t = 0;
no = 0;
memset(head, -1, sizeof(head));
for(int i = 1;i <= n;i++) add(s, i, INF, -1);
for(int i = 1;i <= k;i++)
{
scanf("%d%d%d", &a, &b, &x);
add(a, b, x, i);
}
int res = sap(s, t, n + m + 2);
memset(vis, 0, sizeof(vis));
dfs(s, 0);
dfs(t, 1);
ans.clear();
for(int i = 0;i < no;i += 2)
{
int u = e[i].from, v = e[i].to;
if(e[i].cap - e[i].flow == 0 && vis[u][0] && vis[v][1])
ans.push_back(e[i].id);
}
for(int i = 0;i < ans.size();i++)
{
if(i > 0) printf(" ");
printf("%d", ans[i]);
}
printf("\n");
}
return 0;
}