码迷,mamicode.com
首页 > 其他好文 > 详细

网络流初步

时间:2015-11-23 18:17:52      阅读:219      评论:0      收藏:0      [点我收藏+]

标签:

2015年11月23日

  网络流24题<1> COGS 14

    二分图匹配。

    Dinic:

技术分享
 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (int i = a; i <= b; i++)
 3 #define drep(i, a, b) for (int i = a; i >= b; i--)
 4 #define REP(i, a, b) for (int i = a; i < b; i++)
 5 #define pb push_back
 6 #define mp make_pair
 7 #define clr(x) memset(x, 0, sizeof(x))
 8 #define xx first
 9 #define yy second
10 using namespace std;
11 typedef long long i64;
12 typedef pair<int, int> pii;
13 const int inf = ~0U>>1;
14 const i64 INF = ~0ULL>>1;
15 //***************************
16 
17 const int maxn = 105;
18 struct Ed {
19     int u, v, nx, c; Ed() {}
20     Ed(int _u, int _v, int _nx, int _c) :
21         u(_u), v(_v), nx(_nx), c(_c) {}
22 } E[3005];
23 int G[105], cnt;
24 void addedge(int x, int y, int v) {
25     E[cnt] = Ed(x, y, G[x], v);
26     G[x] = cnt++;
27     E[cnt] = Ed(y, x, G[y], 0);
28     G[y] = cnt++;
29 }
30 
31 int s, t;
32 
33 int level[maxn];
34 bool bfs() {
35     static int que[maxn]; int qt(0), qh(0);
36     clr(level);
37     level[que[++qt] = s] = 1;
38     while (qt != qh) {
39         int x = que[++qh];
40         for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v])
41             level[que[++qt] = E[i].v] = level[x] + 1;
42     }
43     return !!level[t];
44 }
45 int dfs(int u, int rm) {
46     if (u == t) return rm;
47     int rm1 = rm;
48     for (int i = G[u]; i != -1; i = E[i].nx) {
49         if (E[i].c && level[E[i].v] == level[u] + 1) {
50             int flow = dfs(E[i].v, min(E[i].c, rm));
51             E[i].c -= flow, E[i ^ 1].c += flow;
52             if ((rm -= flow) == 0) break;
53         }
54     }
55     if (rm1 == rm) level[u] = 0;
56     return rm1 - rm;
57 }
58 
59 int main() {
60     freopen("flyer.in", "r", stdin);
61     freopen("flyer.out", "w", stdout);
62     int n, n1;
63     while (~scanf("%d%d", &n, &n1)) {
64         s = 0, t = n + 1;
65         memset(G, -1, sizeof(G));
66         int x, y;
67         while (~scanf("%d%d", &x, &y)) addedge(x, y, 1);
68         rep(i, 1, n1) addedge(s, i, 1);
69         rep(i, n1 + 1, n) addedge(i, t, 1);
70         int ans(0);
71         while (bfs()) ans += dfs(s, 0x3f3f3f3f);
72         printf("%d\n", ans);
73     }
74     fclose(stdin);
75     fclose(stdout);
76     return 0;
77 }
View Code

    匈牙利:

技术分享
 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (int i = a; i <= b; i++)
 3 #define drep(i, a, b) for (int i = a; i >= b; i--)
 4 #define REP(i, a, b) for (int i = a; i < b; i++)
 5 #define pb push_back
 6 #define mp make_pair
 7 #define clr(x) memset(x, 0, sizeof(x))
 8 #define xx first
 9 #define yy second
10 using namespace std;
11 typedef long long i64;
12 typedef pair<int, int> pii;
13 const int inf = ~0U>>1;
14 const i64 INF = ~0ULL>>1;
15 //***************************
16 
17 const int maxn = 105;
18 struct Ed {
19     int u, v, nx, c; Ed() {}
20     Ed(int _u, int _v, int _nx) :
21         u(_u), v(_v), nx(_nx) {}
22 } E[3005];
23 int G[105], cnt;
24 void addedge(int x, int y) {
25     E[cnt] = Ed(x, y, G[x]);
26     G[x] = cnt++;
27 }
28 
29 bool used[maxn];
30 int girl[maxn];
31 bool find(int x) {
32     for (int i = G[x]; i != -1; i = E[i].nx) {
33         if (used[E[i].v]) continue;
34         used[E[i].v] = 1;
35         if (!girl[E[i].v] || find(girl[E[i].v])) {
36             girl[E[i].v] = x;
37             return true;
38         }
39     }
40     return false;
41 }
42 int main() {
43     freopen("flyer.in", "r", stdin);
44     freopen("flyer.out", "w", stdout);
45     int n, n1;
46     while (~scanf("%d%d", &n, &n1)) {
47         int x, y;
48         memset(G, -1, sizeof(G));
49         while (~scanf("%d%d", &x, &y)) {
50             addedge(x, y);
51         }
52         clr(girl);
53         int ans(0);
54         rep(i, 1, n1) {
55             clr(used);
56             if (find(i)) ans++;
57         }
58         printf("%d\n", ans);
59     }
60     
61 }
View Code

 

  网络流24题<2> COGS 727

    该问题的一般模型为最大权闭合图。

    [建模方法]

      把每个实验看作二分图X集合中的顶点,每个设备看作二分图Y集合中的顶点,增加源S和汇T。
      1、从S向每个Xi连接一条容量为该点收入的有向边。
      2、从Yi向T连接一条容量为该点支出的有向边。
      3、如果一个实验i需要设备j,连接一条从Xi到Yj容量为无穷大的有向边。

 

    用割来确定答案。

    设S-T割中的S割为选定的答案,A为实验集合,B为器材编号。

      ans:被选中的A集合中的顶点的权值 - 被选中的B集合中的顶点的权值

      Cut:没有被选中的A集合中的顶点的权值 + 被选中的B集合中的顶点的权值 + 被选中的A集合中与没有被选中的B集合中的边的Sum (一些inf的和)
      Total:所有A集合中的顶点的权值
      Total - Cut = ans
      最小割时没有Cut里的第三项,所以最小化Cut,最大流。

技术分享
 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (int i = a; i <= b; i++)
 3 #define drep(i, a, b) for (int i = a; i >= b; i--)
 4 #define REP(i, a, b) for (int i = a; i < b; i++)
 5 #define pb push_back
 6 #define mp make_pair
 7 #define clr(x) memset(x, 0, sizeof(x))
 8 #define xx first
 9 #define yy second
10 using namespace std;
11 typedef long long i64;
12 typedef pair<int, int> pii;
13 const int inf = 0x3f3f3f3f;
14 const i64 INF = ~0ULL>>1;
15 //***************************
16 
17 const int maxn = 205;
18 struct Ed {
19     int u, v, nx, c; Ed() {}
20     Ed(int _u, int _v, int _nx, int _c) :
21         u(_u), v(_v), nx(_nx), c(_c) {}
22 } E[10205];
23 int G[maxn], cnt;
24 void addedge(int x, int y, int v) {
25     E[cnt] = Ed(x, y, G[x], v);
26     G[x] = cnt++;
27     E[cnt] = Ed(y, x, G[y], 0);
28     G[y] = cnt++;
29 }
30 
31 int s, t;
32 int level[maxn];
33 bool bfs() {
34     static int que[maxn]; int qh(0), qt(0);
35     clr(level);
36     level[que[++qt] = s] = 1;
37     while (qh != qt) {
38         int x = que[++qh];
39         for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v]) 
40             level[que[++qt] = E[i].v] = level[x] + 1;
41     }
42     return !!level[t];
43 }
44 int dfs(int u, int rm) {
45     if (u == t) return rm;
46     int rm1 = rm;
47     for (int i = G[u]; i != -1; i = E[i].nx) {
48         if (E[i].c && level[E[i].v] == level[u] + 1) {
49             int flow = dfs(E[i].v, min(rm, E[i].c));
50             E[i].c -= flow, E[i ^ 1].c += flow;
51             if ((rm -= flow) == 0) break;
52         }
53     }
54     if (rm1 == rm) level[u] = 0;
55     return rm1 - rm;
56 }
57 
58 char ch[100005];
59 int main() {
60     freopen("shuttle.in", "r", stdin);
61     freopen("shuttle.out", "w", stdout);
62     int n, m;
63     int tot(0);
64     scanf("%d%d", &n, &m);
65     memset(G, -1, sizeof(G));
66     s = 0, t = n + m + 1;
67     rep(i, 1, n) {
68         int val;
69         scanf("%d ", &val);
70         tot += val;
71         addedge(s, i, val);
72         fgets(ch, 100000, stdin);
73         int id(0);
74         for (int j = 0; ch[j]; j++) {
75             if (ch[j] ==   || ch[j] == \n || ch[j] == \r) {
76                 if (id) addedge(i, id + n, inf);
77                 id = 0;
78             }
79             else {
80                 id = id * 10 + ch[j] - 0;
81             }
82         }
83     }
84     rep(i, 1, m) {
85         int val;
86         scanf("%d", &val);
87         addedge(n + i, t, val);
88     }
89     int ans(0);
90     while (bfs()) ans += dfs(s, 0x3f3f3f3f);
91     rep(i, 1, n) if (level[i]) printf("%d ", i);
92     puts("");
93     rep(i, 1, m) if (level[i + n]) printf("%d ", i);
94     puts("");
95     printf("%d\n", tot - ans);
96     return 0;
97 }
View Code

 

  网络流24题<3> COGS 728

    二分图最大匹配。假设一开始n个点自己是一条链,那么此时有n条链,假设可以匹配一个,那么路径数就会减一,所以跑出最大匹配即可。

    懒,只写了dinic:

技术分享
  1 #include <bits/stdc++.h>
  2 #define rep(i, a, b) for (int i = a; i <= b; i++)
  3 #define drep(i, a, b) for (int i = a; i >= b; i--)
  4 #define REP(i, a, b) for (int i = a; i < b; i++)
  5 #define pb push_back
  6 #define mp make_pair
  7 #define clr(x) memset(x, 0, sizeof(x))
  8 #define xx first
  9 #define yy second
 10 using namespace std;
 11 typedef long long i64;
 12 typedef pair<int, int> pii;
 13 const int inf = 0x3f3f3f3f;
 14 const i64 INF = ~0ULL>>1;
 15 //***************************
 16 
 17 const int maxn = 305;
 18 
 19 struct Ed {
 20     int u, v, c, nx; Ed() {}
 21     Ed(int _u, int _v, int _c, int _nx) :
 22         u(_u), v(_v), c(_c), nx(_nx) {}
 23 } E[13005];
 24 int G[305], cnt;
 25 void addedge(int u, int v, int c) {
 26     E[cnt] = Ed(u, v, c, G[u]);
 27     G[u] = cnt++;
 28     E[cnt] = Ed(v, u, 0, G[v]);
 29     G[v] = cnt++;
 30 }
 31 
 32 int level[maxn];
 33 int s, t;
 34 bool bfs() {
 35     static int que[305]; int qh(0), qt(0);
 36     clr(level);
 37     level[que[++qt] = s] = 1;
 38     while (qh != qt) {
 39         int x = que[++qh];
 40         for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v])
 41             level[que[++qt] = E[i].v] = level[x] + 1;
 42     }
 43     return !!level[t];
 44 }
 45 int dfs(int u, int rm) {
 46     if (u == t) return rm;
 47     int rm1 = rm;
 48     for (int i = G[u]; i != -1; i = E[i].nx) {
 49         if (E[i].c && level[E[i].v] == level[u] + 1) {
 50             int flow = dfs(E[i].v, min(rm, E[i].c));
 51             E[i].c -= flow, E[i ^ 1].c += flow;
 52             if ((rm -= flow) == 0) break;
 53         }
 54     }
 55     if (rm1 == rm) level[u] = 0;
 56     return rm1 - rm;
 57 }
 58 
 59 int main() {
 60     freopen("path3.in", "r", stdin);
 61     freopen("path3.out", "w", stdout);
 62     int n, m;
 63     scanf("%d%d", &n, &m);
 64     s = 0, t = (n << 1) + 1;
 65     memset(G, -1, sizeof(G));
 66     rep(i, 1, m) {
 67         int x, y;
 68         scanf("%d%d", &x, &y);
 69         addedge(x, y + n, 1);
 70     }
 71     rep(i, 1, n) {
 72         addedge(s, i, 1);
 73         addedge(i + n, t, 1);
 74     }
 75     while (bfs()) dfs(s, 0x3f3f3f3f);
 76     static int nxt[maxn], frm[maxn];
 77     rep(i, 1, n) {
 78         for (int j = G[i]; j != -1; j = E[j].nx) {
 79             if (E[j].v <= n) continue;
 80             if (E[j].c == 0) {
 81                 nxt[i] = E[j].v - n, frm[E[j].v - n] = i;
 82                 break;
 83             }
 84         }
 85     }
 86     int ans(0);
 87     rep(i, 1, n) {
 88         if (frm[i] == 0) {
 89             int k = i;
 90             while (k) {
 91                 printf("%d ", k);
 92                 k = nxt[k];
 93             }
 94             puts("");
 95             ans++;
 96         }
 97     }
 98     printf("%d\n", ans);
 99     fclose(stdin);
100     fclose(stdout);
101     return 0;
102 }
View Code

    匈牙利算法请见友链中的Ngshily.   http://www.cnblogs.com/Ngshily/p/4988909.html

    

网络流初步

标签:

原文地址:http://www.cnblogs.com/y7070/p/4988800.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!