UVa 1440:Inspection(带下界的最小流)***

https://vjudge.net/problem/UVA-1440

题意:给出一个图,要求每条边都必须至少走一次,问最少需要一笔画多少次。

思路:看了好久才勉强看懂模板。良心推荐:学习地址

看完这个大概就能懂了。

那条T->S的边的反向边的流量就是可行流的流量。
最小流就是去掉新的源点和新的汇点(保证必要弧)和T->S边后,从T往S跑最大流(尽量退流),最小流的答案就是原来T->S的反向边流量 - 第二次最大流的流量。
最大流就是去掉新的源点和新的汇点之后,再跑一遍最大流得到的就是答案。

最小流这里后面看别人的发现别人是先跑一遍(SS->ST)最大流,然后再连<T,S>边,再跑一遍(SS->ST)最大流。然而论文里面是先连<T,S>边,跑一遍(SS->ST)最大流,然后删掉<T,S>边和所有与SS、ST相连的边,跑一遍(T->S)的最大流。

看了N久还是不能完全理解。

记得多组数组!!!WA了一晚上。

写法一:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define N 210
  4 #define INF 0x3f3f3f3f
  5 struct Edge {
  6     int u, v, nxt, cap;
  7 } edge[N*N];
  8 int head[N], tot, dis[N], cur[N], pre[N], gap[N], in[N], out[N], S, T, SS, ST;
  9 
 10 void Add(int u, int v, int cap) {
 11     edge[tot].u = u, edge[tot].v = v, edge[tot].nxt = head[u], edge[tot].cap = cap, head[u] = tot++;
 12     edge[tot].u = v, edge[tot].v = u, edge[tot].nxt = head[v], edge[tot].cap = 0, head[v] = tot++;
 13 }
 14 
 15 int BFS(int T) {
 16     memset(dis, INF, sizeof(dis));
 17     memset(gap, 0, sizeof(gap));
 18     memcpy(cur, head, sizeof(cur));
 19     dis[T] = 0, gap[0]++;
 20     queue<int> que; que.push(T);
 21     while(!que.empty()) {
 22         int u = que.front(); que.pop();
 23         for(int i = head[u]; ~i; i = edge[i].nxt) {
 24             int v = edge[i].v;
 25             if(dis[v] == INF) {
 26                 dis[v] = dis[u] + 1;
 27                 gap[dis[v]]++;
 28                 que.push(v);
 29             }
 30         }
 31     }
 32 }
 33 
 34 int ISAP(int S, int T, int n) {
 35     BFS(T);
 36     int u = pre[S] = S, i, index, flow, ans = 0;
 37     while(dis[S] < n) {
 38         if(u == T) {
 39             flow = INF;
 40             for(i = S; i != T; i = edge[cur[i]].v)
 41                 if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
 42             for(i = S; i != T; i = edge[cur[i]].v)
 43                 edge[cur[i]].cap -= flow, edge[cur[i]^1].cap += flow;
 44             ans += flow, u = index;
 45         }
 46         for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap && dis[edge[i].v] + 1 == dis[u]) break;
 47         if(~i) {
 48             cur[u] = i; pre[edge[i].v] = u; u = edge[i].v;
 49         } else {
 50             if(--gap[dis[u]] == 0) break;
 51             int md = n;
 52             for(int i = head[u]; ~i; i = edge[i].nxt)
 53                 if(edge[i].cap && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i;
 54             gap[dis[u] = md + 1]++;
 55             u = pre[u];
 56         }
 57     }
 58     return ans;
 59 }
 60 
 61 void Delete() {
 62     for(int i = head[SS]; ~i; i = edge[i].nxt) edge[i].cap = edge[i^1].cap = 0;
 63     for(int i = head[ST]; ~i; i = edge[i].nxt) edge[i].cap = edge[i^1].cap = 0;
 64     edge[tot-1].cap = edge[(tot-1)^1].cap = 0;
 65 }
 66 
 67 void Update(int n) {
 68     for(int u = 1; u <= n; u++) {
 69         for(int i = head[u]; ~i; i = edge[i].nxt) {
 70             if(edge[i].v == S || edge[i].v == T || (i & 1)) continue;
 71             edge[i^1].cap++;
 72         }
 73     }
 74 }
 75 
 76 void Dfs(int u) {
 77     for(int i = head[u]; ~i; i = edge[i].nxt) {
 78         int v = edge[i].v;
 79         if(i & 1 || !edge[i^1].cap || v == S || v == T || v == SS || v == ST) continue;
 80         edge[i^1].cap--;
 81         printf(" %d", v);
 82         Dfs(v);
 83         break;
 84     }
 85 }
 86 
 87 int main() {
 88     int n;
 89     while(~scanf("%d", &n)) {
 90         memset(head, -1, sizeof(head)); tot = 0;
 91         memset(out, 0, sizeof(out)); memset(in, 0, sizeof(in));
 92         S = n + 1, T = n + 2, SS = n + 3, ST = n + 4;
 93         for(int i = 1; i <= n; i++) {
 94             int k; scanf("%d", &k);
 95             while(k--) {
 96                 int x; scanf("%d", &x);
 97                 out[i]++; in[x]++;
 98                 Add(i, x, INF);
 99             }
100         }
101         for(int i = 1; i <= n; i++) {
102             if(!out[i]) Add(i, T, INF);
103             if(!in[i]) Add(S, i, INF);
104             int deg = in[i] - out[i];
105             if(deg > 0) Add(SS, i, deg);
106             else if(deg < 0) Add(i, ST, -deg);
107         }
108         Add(T, S, INF);
109         ISAP(SS, ST, ST + 1);
110         int ans = edge[tot-1].cap;
111         Delete();
112         ans -= ISAP(T, S, T + 1);
113         printf("%d
", ans);
114         Update(n);
115         int cur = head[S];
116         for(int k = 1; k <= ans; k++) {
117             for(int i = cur; ~i; i = edge[i].nxt) {
118                 if(!(i & 1) && edge[i^1].cap) {
119                     int v = edge[i].v;
120                     edge[i^1].cap--;
121                     printf("%d", v);
122                     Dfs(edge[i].v);
123                     puts("");
124                     cur = i;
125                     break;
126                 }
127             }
128         }
129     }
130     return 0;
131 }

写法二:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define N 210
  4 #define INF 0x3f3f3f3f
  5 struct Edge {
  6     int u, v, nxt, cap;
  7 } edge[N*N];
  8 int head[N], tot, dis[N], cur[N], pre[N], gap[N], in[N], out[N], S, T, SS, ST, n;
  9 
 10 void Add(int u, int v, int cap) {
 11     edge[tot].u = u, edge[tot].v = v, edge[tot].nxt = head[u], edge[tot].cap = cap, head[u] = tot++;
 12     edge[tot].u = v, edge[tot].v = u, edge[tot].nxt = head[v], edge[tot].cap = 0, head[v] = tot++;
 13 }
 14 
 15 int BFS(int T) {
 16     memset(dis, INF, sizeof(dis));
 17     memset(gap, 0, sizeof(gap));
 18     memcpy(cur, head, sizeof(cur));
 19     dis[T] = 0, gap[0]++;
 20     queue<int> que; que.push(T);
 21     while(!que.empty()) {
 22         int u = que.front(); que.pop();
 23         for(int i = head[u]; ~i; i = edge[i].nxt) {
 24             int v = edge[i].v;
 25             if(dis[v] == INF) {
 26                 dis[v] = dis[u] + 1;
 27                 gap[dis[v]]++;
 28                 que.push(v);
 29             }
 30         }
 31     }
 32 }
 33 
 34 int ISAP(int S, int T, int n) {
 35     BFS(T);
 36     int u = pre[S] = S, i, index, flow, ans = 0;
 37     while(dis[S] < n) {
 38         if(u == T) {
 39             flow = INF;
 40             for(i = S; i != T; i = edge[cur[i]].v)
 41                 if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
 42             for(i = S; i != T; i = edge[cur[i]].v)
 43                 edge[cur[i]].cap -= flow, edge[cur[i]^1].cap += flow;
 44             ans += flow, u = index;
 45         }
 46         for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap && dis[edge[i].v] + 1 == dis[u]) break;
 47         if(~i) {
 48             cur[u] = i; pre[edge[i].v] = u; u = edge[i].v;
 49         } else {
 50             if(--gap[dis[u]] == 0) break;
 51             int md = n;
 52             for(int i = head[u]; ~i; i = edge[i].nxt)
 53                 if(edge[i].cap && dis[edge[i].v] < md) md = dis[edge[i].v], cur[u] = i;
 54             gap[dis[u] = md + 1]++;
 55             u = pre[u];
 56         }
 57     }
 58     return ans;
 59 }
 60 
 61 void Delete() {
 62     for(int i = head[SS]; ~i; i = edge[i].nxt) edge[i].cap = edge[i^1].cap = 0;
 63     for(int i = head[ST]; ~i; i = edge[i].nxt) edge[i].cap = edge[i^1].cap = 0;
 64     edge[tot-1].cap = edge[(tot-1)^1].cap = 0;
 65 }
 66 
 67 void Update(int n) {
 68     for(int u = 1; u <= n; u++) {
 69         for(int i = head[u]; ~i; i = edge[i].nxt) {
 70             if(edge[i].v == S || edge[i].v == T || (i & 1)) continue;
 71             edge[i^1].cap++;
 72         }
 73     }
 74 }
 75 
 76 void Dfs(int u) {
 77     for(int i = head[u]; ~i; i = edge[i].nxt) {
 78         int v = edge[i].v;
 79         if(i & 1 || !edge[i^1].cap || v > n) continue;
 80         edge[i^1].cap--;
 81         printf(" %d", v);
 82         Dfs(v); break;
 83     }
 84 }
 85 
 86 void Solve() {
 87     for(int u = 1; u <= n; u++) {
 88         for(int i = head[u]; ~i; i = edge[i].nxt) {
 89             int v = edge[i].v;
 90             if(i & 1) continue;
 91             edge[i^1].cap++;
 92         }
 93     }
 94     for(int i = head[S]; ~i; i = edge[i].nxt) {
 95         if(i & 1) continue;
 96         while(edge[i^1].cap) {
 97             edge[i^1].cap--;
 98             int v = edge[i].v;
 99             printf("%d", v);
100             Dfs(v); puts("");
101         }
102     }
103 }
104 
105 int main() {
106     while(~scanf("%d", &n)) {
107         memset(head, -1, sizeof(head)); tot = 0;
108         memset(out, 0, sizeof(out)); memset(in, 0, sizeof(in));
109         S = n + 1, T = n + 2, SS = n + 3, ST = n + 4;
110         for(int i = 1; i <= n; i++) {
111             int k; scanf("%d", &k);
112             while(k--) {
113                 int x; scanf("%d", &x);
114                 out[i]++; in[x]++;
115                 Add(i, x, INF);
116             }
117         }
118         for(int i = 1; i <= n; i++) {
119             if(!out[i]) Add(i, T, INF);
120             if(!in[i]) Add(S, i, INF);
121             int deg = in[i] - out[i];
122             if(deg > 0) Add(SS, i, deg);
123             else if(deg < 0) Add(i, ST, -deg);
124         }
125         ISAP(SS, ST, ST + 1);
126         Add(T, S, INF);
127         int ans = ISAP(SS, ST, ST + 1);
128         printf("%d
", ans);
129         Solve();
130     }
131     return 0;
132 }
原文地址:https://www.cnblogs.com/fightfordream/p/6736429.html