原题链接
- 题意:给一个流网络,问有多少条边,使得增加他们容量可以增加最大流。
- 题解:就是先跑出最大可行流,首先 (f(u, v)
eq 0),那么这条边不可以作为,
显然其实感性理解就可以了。然后再枚举边,看看边的左端点是否存在一条路径从源点到左端点,边的右端点是否存在一条路径从右端点到汇点,如果都成立并且 (f(u, v) = 0) 那么这条边就可对答案做出贡献。
- 代码:
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1e5, M = 1e6, inf = 99999999;
int h[N], to[M], f[M], ne[M], idx;
void add(int u, int v, int w) {
ne[idx] = h[u], to[idx] = v, f[idx] = w, h[u] = idx++;
ne[idx] = h[v], to[idx] = u, f[idx] = 0, h[v] = idx++;
}
int S, T;
int d[N], cur[N];
queue<int>q;
bool bfs() {
while (!q.empty())q.pop();
q.push(S);
memset(d, -1, sizeof d);
cur[S] = h[S];
d[S] = 0;
while (!q.empty()) {
auto u = q.front();q.pop();
for (int i = h[u]; ~i; i = ne[i]) {
int v = to[i];
if (d[v] == -1 && f[i]) {
cur[v] = h[v];
q.push(v);
d[v] = d[u] + 1;
if (v == T)return 1;
}
}
}
return 0;
}
int dfs(int u, int limit) {
if (u == T)return limit;
int flow = 0;
for (int i = cur[u]; ~i; i = ne[i]) {
int v = to[i];
cur[u] = i;
if (d[v] == d[u] + 1 && f[i]) {
int t = dfs(v, min(f[i], limit - flow));
flow += t;
f[i] -= t;
f[i ^ 1] += t;
}
}
return flow;
}
int dinic() {
int ret =0 , flow;
while (bfs()) {//cout << "?";
while (flow = dfs(S, inf))
ret += flow;
}
return ret;
}
bool vis[2][N];
void dfs1(int u,int op) {
vis[op][u] = 1;
for (int i = h[u]; ~i; i = ne[i]) {
int v = to[i];
int j = op ^ i;
if (f[j] && !vis[op][v]) {
dfs1(v, op);
}
}
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
T = n-1;
for (int i = 1; i <= m; i ++) {
int u, v, w;scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
}
int x = dinic();
dfs1(S, 0);
dfs1(T, 1);
int ans = 0;
for (int i = 0; i < m * 2; i += 2) {
int u = to[i ^ 1];
int v = to[i];
if (f[i] == 0 && vis[0][u] && vis[1][v]) {
ans++;
}
}
printf("%d
", ans);
}