【题意】:给出一幅图,求边最小的最小割。
【题解】:求两次最小割。
第一次求出所有割边。
然后把割边容量设成1,非割边容量为inf,再求一次最小割即为答案。
【代码】:
1 #include "iostream"
2 #include "cstdio"
3 #include "cstring"
4 using namespace std;
5 #define maxn 1000
6 #define maxm 500000
7 const int inf = 1 << 30;
8 int s, t, n, m;
9 int eh[maxn], low[maxn], dist[maxn], cnt[maxn], tot, pre[maxn], cur[maxn];
10 bool color[maxn];
11 struct Edge {
12 int u, v, cap, flow, next;
13 }et[maxm];
14
15 void init() {
16 tot = 0;
17 memset(eh, -1, sizeof(eh));
18 }
19
20 void add(int u, int v, int cap, int flow) {
21 Edge e = {u, v, cap, flow, eh[u]};
22 et[tot] = e;
23 eh[u] = tot++;
24 }
25
26 void addedge(int u, int v, int cap) {
27 add(u, v, cap, 0), add(v, u, 0, 0);
28 }
29
30 int isap(int s, int t, int n) {
31 int u, v, now, flow = 0;
32 memset(low, 0, sizeof(low));
33 memset(cnt, 0, sizeof(cnt));
34 memset(dist, 0, sizeof(dist));
35 for(u = 0; u <= n; u++) cur[u] = eh[u];
36 low[s] = inf, cnt[0] = n;
37 u = s;
38 while(dist[s] < n) {
39 for(now = cur[u]; now != -1; now = et[now].next)
40 if(et[now].cap - et[now].flow && dist[u] == dist[v = et[now].v] + 1) break;
41 if(now != -1) {
42 cur[u] = pre[v] = now;
43 low[v] = min(low[u], et[now].cap - et[now].flow);
44 u = v;
45 if(u == t) {
46 for(; u != s; u = et[pre[u]].u) {
47 et[pre[u]].flow += low[t];
48 et[pre[u]^1].flow -= low[t];
49 }
50 low[s] = inf, flow += low[t];
51 }
52 } else {
53 if(--cnt[dist[u]] == 0) break;
54 dist[u] = n;
55 cur[u] = eh[u];
56 for(now = eh[u]; now != -1; now = et[now].next)
57 if(et[now].cap - et[now].flow && dist[u] > dist[v = et[now].v] + 1)
58 dist[u] = dist[v] + 1;
59 cnt[dist[u]]++;
60 if(u != s) u = et[pre[u]].u;
61 }
62 }
63 return flow;
64 }
65
66 void dfs(int u) {
67 color[u] = 1;
68 for(int i = eh[u]; i != -1; i = et[i].next)
69 if(!color[et[i].v] && et[i].cap - et[i].flow)
70 dfs(et[i].v);
71 }
72
73 int main() {
74 int T;
75 scanf("%d", &T);
76 for(int tt = 1; tt <= T; tt++) {
77 scanf("%d%d", &n, &m);
78 init();
79 s = 0, t = n - 1;
80 for(int i = 0; i < m; i++) {
81 int u, v, cap, d;
82 scanf("%d%d%d%d", &u, &v, &cap, &d);
83 if(d) addedge(u, v, cap), addedge(v, u, cap);
84 else addedge(u, v, cap);
85 }
86 isap(s, t, n);
87 for(int i = 0; i < tot; i += 2) {
88 if(et[i].cap == et[i].flow) et[i].cap = 1, et[i].flow = 0;
89 else et[i].flow = 0;
90 et[i^1].cap = et[i^1].flow = 0;
91 }
92 int ans = isap(s, t, n);
93 printf("Case %d: %d\n", tt, ans);
94 }
95 }
96