最大流最小割费用流初步

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

    

  bzoj 3996

    同类与网络流24题<2>,最大权闭合图。

    D =(A * B - C)* A^T;

    E = A * B;

    Eij = sigma(k = (1 ~ n)) Aik * Bkj;因为 E为[1,n]的矩阵 把Eij表示为Ej.

    Ej = sigma(k = (1 ~ n)) Ak * Bkj;

    设F = E * A^T;

    F(1, 1) = sigma(p = 1 ~n) Ep * Ap;

    代入得 F = sigma(p = 1 ~ n) (sigma(k = 1 ~ n) Ak * Bkp * Ap)

    

    G = C * A^T

    G = sigma(k, 1, n) Ck * Ak;

    由此可见,若要取得Bkp,则Ak和Ap必须为1,也就是Bij依赖Ai和Aj,后面的式子则是Ai的选取代价,所以得到了最大权闭合图的模型。

 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 = 260005;
18 const int maxm = 751005;
19  
20 struct Ed {
21     int u, v, nx, c; Ed() {}
22     Ed(int _u, int _v, int _nx, int _c) :
23         u(_u), v(_v), nx(_nx), c(_c) {}
24 } E[maxm << 1];
25 int G[maxn], cnt;
26 void addedge(int u, int v, int c) {
27     E[cnt] = Ed(u, v, G[u], c);
28     G[u] = cnt++;
29     E[cnt] = Ed(v, u, G[v], 0);
30     G[v] = cnt++;
31 }
32  
33 int s, t;
34 int level[maxn];
35 bool bfs() {
36     static int que[maxn]; int qh(0), qt(0);
37     clr(level);
38     level[que[++qt] = s] = 1;
39     while (qh != qt) {
40         int x = que[++qh];
41         for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v])
42             level[que[++qt] = E[i].v] = level[x] + 1;
43     }
44     return !!level[t];
45 }
46 int dfs(int u, int rm) {
47     if (u == t) return rm;
48     int rm1 = rm;
49     for (int i = G[u]; i != -1; i = E[i].nx) {
50         if (E[i].c && level[E[i].v] == level[u] + 1) {
51             int flow = dfs(E[i].v, min(E[i].c, rm));
52             E[i].c -= flow, E[i ^ 1].c += flow;
53             if ((rm -= flow) == 0) break;
54         }
55     }
56     if (rm1 == rm) level[u] = 0;
57     return rm1 - rm;
58 }
59  
60 int main() {
61     int n;
62     scanf("%d", &n);
63     s = 0, t = n * n + n + 1;
64     memset(G, -1, sizeof(G));
65     int tot(0);
66     REP(i, 0, n) rep(j, 1, n) {
67         int id;
68         scanf("%d", &id);
69         tot += id;
70         addedge(s, i * n + j, id);
71         addedge(i * n + j, i + n * n + 1, inf);
72         addedge(i * n + j, j + n * n, inf);
73     }
74     rep(i, 1, n) {
75         int id;
76         scanf("%d", &id);
77         addedge(n * n + i, t, id);
78     }
79     int ans(0);
80     while (bfs()) ans += dfs(s, 0x3f3f3f3f);
81     printf("%d\n", tot - ans);
82     return 0;
83 }
View Code

  

  网络流24题<5> COGS 729 圆桌问题

    类似于二分图匹配,给每个单位连他们人数的流量,每个单位依次给每个桌子连1的流量,每个桌子依次给超级汇点连桌子的容量的流量。

    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 = 505;
18 const int maxm = 41000;
19 
20 struct Ed {
21     int u, v, nx, c; Ed() {}
22     Ed(int _u, int _v, int _nx, int _c) :
23         u(_u), v(_v), nx(_nx), c(_c) {}
24 } E[maxm << 1];
25 int G[maxn], cnt;
26 void addedge(int u, int v, int c) {
27     E[cnt] = Ed(u, v, G[u], c);
28     G[u] = cnt++;
29     E[cnt] = Ed(v, u, G[v], 0);
30     G[v] = cnt++;
31 }
32 
33 int s, t;
34 int level[maxn];
35 bool bfs() {
36     static int que[maxn]; int qh(0), qt(0);
37     clr(level);
38     level[que[++qt] = s] = 1;
39     while (qh != qt) {
40         int x = que[++qh];
41         for (int i = G[x]; i != -1; i = E[i].nx) if (E[i].c && !level[E[i].v])
42             level[que[++qt] = E[i].v] = level[x] + 1;
43     }
44     return !!level[t];
45 }
46 int dfs(int u, int rm) {
47     if (u == t) return rm;
48     int rm1 = rm;
49     for (int i = G[u]; i != -1; i = E[i].nx) {
50         if (E[i].c && level[E[i].v] == level[u] + 1) {
51             int flow = dfs(E[i].v, min(rm, E[i].c));
52             E[i].c -= flow, E[i ^ 1].c += flow;
53             if ((rm -= flow) == 0) break;
54         }
55     }
56     if (rm1 == rm) level[u] = 0;
57     return rm1 - rm;
58 }
59 
60 int main() {
61     freopen("roundtable.in", "r", stdin);
62     freopen("roundtable.out", "w", stdout);
63     int n, m;
64     scanf("%d%d", &n, &m);
65     s = 0, t = n + m + 1;
66     memset(G, -1, sizeof(G));
67     int tot(0);
68     rep(i, 1, n) {
69         int id;
70         scanf("%d", &id);
71         tot += id;
72         addedge(s, i, id);
73     }
74     rep(i, 1, n) rep(j, 1, m) addedge(i, n + j, 1);
75     rep(i, 1, m) {
76         int id;
77         scanf("%d", &id);
78         addedge(n + i, t, id);
79     }
80     int ans(0);
81     while (bfs()) ans += dfs(s, 0x3f3f3f3f);
82     if (ans < tot) puts("0");
83     else puts("1");
84     static int sta[maxn];
85     int top(0);
86     rep(i, 1, n) {
87         for (int j = G[i]; j != -1; j = E[j].nx) {
88             if (E[j].c == 0) {
89                 sta[++top] = E[j].v - n;
90             }
91         }
92         drep(j, top, 1) printf("%d ", sta[j]);
93         top = 0;
94         puts("");
95     }
96     fclose(stdin);
97     fclose(stdout);
98     return 0;
99 }
View Code

 

2015年11月24日

  网络流24题 COGS 魔术球问题

    最小路径覆盖问题。

    先二分答案,建图dinic即可,有一点需要注意,在连边时,i 只能向 i + 1 及其以后的边连边,否则不符合实际意义,也会使二分图满流。

 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (register 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 = 3205;
18 const int maxm = 38545;
19 
20 struct Ed {
21     int u, v, nx, c; Ed() {}
22     Ed(int _u, int _v, int _nx, int _c) :
23         u(_u), v(_v), nx(_nx), c(_c) {}
24 } E[maxm << 1];
25 int G[maxn], cnt;
26 void addedge(int u, int v, int c) {
27     E[cnt] = Ed(u, v, G[u], c);
28     G[u] = cnt++;
29     E[cnt] = Ed(v, u, G[v], 0);
30     G[v] = cnt++;
31 }
32 
33 int level[maxn], s, t;
34 bool bfs() {
35     static int que[maxn]; 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(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("balla.in", "r", stdin);
61     freopen("balla.out", "w", stdout);
62     int sho;
63     scanf("%d", &sho);
64     int low = 0, high = 1605;
65     while (low < high - 1) {
66         int mid = low + high >> 1;
67         s = 0, t = (mid << 1) + 1;
68         memset(G, -1, sizeof(G)); cnt = 0;
69         rep(i, 1, mid) rep(j, i + 1, mid) {
70             int sq = sqrt(1.0 * i + j);
71             if (sq * sq == i + j) addedge(i, mid + j, 1);
72         }
73         rep(i, 1, mid) addedge(s, i, 1), addedge(i + mid, t, 1);
74         int ans(0);
75         while (bfs()) ans += dfs(s, 0x3f3f3f3f);
76         if (mid - ans <= sho) low = mid;
77         else high = mid;
78     }
79     printf("%d\n", low);
80     fclose(stdin);
81     fclose(stdout);
82     return 0;
83 }
View Code

 

2015年11月26日

  网络流24题 10 餐巾计划

    把每个点拆成两个点,一个是每天用掉的点,另一边为来源。

    从S到用掉的点连接费用为0,容量为ri的边。

    从来源的点向T连接费用为0,容量为ri的边。   来限制流量。

    在用掉的点的集合中,i 向 i + 1 连接费用为0,容量为inf的边。

    从S到来源集合中连接容量为inf,费用为P的边。

    连上快洗和慢洗。

    感觉第一个集合中的点中用作限制,第二个才是解决的方案。

 

    zkw费用流:

 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (int i = a; i <= b; i++)
 3 #define REP(i, a, b) for (int i = a; i < b; i++)
 4 #define drep(i, a, b) for (int i = a; i >= b; i--)
 5 #define clr(x) memset(x, 0, sizeof(x))
 6 #define pb push_back
 7 #define mp make_pair
 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 = 405, maxm = 40605;
18 struct Ed {
19     int u, v, nx, c, s; Ed() {};
20     Ed (int _u, int _v, int _nx, int _c, int _s) :
21         u(_u), v(_v), nx(_nx), c(_c), s(_s) {}
22 } E[maxm << 1];
23 int G[maxn], cnt;
24 void addedge(int u, int v, int c, int s) {
25     E[cnt] = Ed(u, v, G[u], c, s);
26     G[u] = cnt++;
27     E[cnt] = Ed(v, u, G[v], 0, -s);
28     G[v] = cnt++;
29 }
30 
31 int s, t;
32 int dis[maxn], vis[maxn];
33 bool spfa() {
34     static int que[maxm]; int qh(0), qt(0);
35     memset(dis, 0x3f, sizeof(dis));
36     clr(vis);
37     vis[que[++qt] = s] = 1; dis[s] = 0;
38     while (qh != qt) {
39         int x = que[++qh]; vis[x] = 0;
40         for (int i = G[x]; i != -1; i = E[i].nx) {
41             if (E[i].c && E[i].s + dis[x] < dis[E[i].v]) {
42                 dis[E[i].v] = dis[x] + E[i].s;
43                 if (!vis[E[i].v]) que[++qt] = E[i].v, vis[E[i].v] = 1;
44             }
45         }
46     }
47     return dis[t] != 0x3f3f3f3f;
48 }
49 
50 int ans;
51 int dfs(int u, int rm) {
52     vis[u] = 1;
53     if (u == t) return rm;
54     int rm1 = rm;
55     for (int i = G[u]; i != -1; i = E[i].nx) {
56         if (dis[u] + E[i].s == dis[E[i].v] && E[i].c && !vis[E[i].v]) {
57             int flow = dfs(E[i].v, min(rm, E[i].c));
58             E[i].c -= flow, E[i ^ 1].c += flow;
59             ans += flow * E[i].s;
60             if ((rm -= flow) == 0) break;
61         }
62     }
63     if (rm1 == rm) dis[u] = 0;
64     return rm1 - rm;
65 }
66 
67 int a[maxn];
68 int main() {
69     freopen("napkin.in", "r", stdin);
70     freopen("napkin.out", "w", stdout);
71     int n;
72     scanf("%d", &n);
73     rep(i, 1, n) scanf("%d", &a[i]);
74     int P, M, F, N, S;
75     scanf("%d%d%d%d%d", &P, &M, &F, &N, &S);
76     memset(G, -1, sizeof(G)); s = 0, t = (n << 1) + 1;
77     rep(i, 1, n) addedge(s, i, a[i], 0), addedge(s, n + i, inf, P), addedge(i + n, t, a[i], 0);
78     REP(i, 1, n) addedge(i, i + 1, inf, 0);
79     rep(i, 1, n) {
80         if (i + M <= n) addedge(i, i + M + n, inf, F);
81         if (i + N <= n) addedge(i, i + N + n, inf, S);
82     }
83 
84     while (spfa()) clr(vis), dfs(s, 0x3f3f3f3f);
85     printf("%d\n", ans);
86     fclose(stdin);
87     fclose(stdout);
88     return 0;
89 }
View Code

    普通费用流:

 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (int i = a; i <= b; i++)
 3 #define REP(i, a, b) for (int i = a; i < b; i++)
 4 #define drep(i, a, b) for (int i = a; i >= b; i--)
 5 #define pb push_back
 6 #define mp make_pair
 7 #define xx first
 8 #define yy second
 9 using namespace std;
10 typedef long long i64;
11 typedef pair<int, int> pii;
12 const int inf = ~0U >> 1;
13 const i64 INF = ~0ULL >> 1;
14 //*****************************
15 
16 const int maxn = 405, maxm = 40605;
17 struct Ed {
18     int u, v, nx, c, s; Ed() {};
19     Ed (int _u, int _v, int _nx, int _c, int _s) :
20         u(_u), v(_v), nx(_nx), c(_c), s(_s) {}
21 } E[maxm << 1];
22 int G[maxn], cnt;
23 void addedge(int u, int v, int c, int s) {
24     E[cnt] = Ed(u, v, G[u], c, s);
25     G[u] = cnt++;
26     E[cnt] = Ed(v, u, G[v], 0, -s);
27     G[v] = cnt++;
28 }
29 
30 bool vis[maxn];
31 int s, t;
32 int pre[maxn];
33 bool spfa() {
34     static int que[maxm]; int qh(0), qt(0);
35     static int dis[maxn];
36     memset(dis, 0x3f, sizeof(dis));
37     memset(vis, 0, sizeof(vis));
38     vis[que[++qt] = s] = 1;
39     dis[s] = 0;
40     while (qh != qt) {
41         int x = que[++qh];
42         vis[x] = 0;
43         for (int i = G[x]; i != -1; i = E[i].nx) {
44             if (E[i].c && dis[x] + E[i].s < dis[E[i].v]) {
45                 dis[E[i].v] = dis[x] + E[i].s;
46                 pre[E[i].v] = i;
47                 if (!vis[E[i].v]) {
48                     vis[E[i].v] = 1;
49                     que[++qt] = E[i].v;
50                 }
51             }
52         }
53     }
54     if (dis[t] == 0x3f3f3f3f) return false;
55     return true;
56 }
57 
58 int a[maxn];
59 int main() {
60     freopen("napkin.in", "r", stdin);
61     freopen("napkin.out", "w", stdout);
62     int n;
63     scanf("%d", &n);
64     rep(i, 1, n) scanf("%d", &a[i]);
65     int P, M, F, N, S;
66     scanf("%d%d%d%d%d", &P, &M, &F, &N, &S);
67 
68     memset(G, -1, sizeof(G));
69     s = 0, t = (n << 1) + 1;
70     rep(i, 1, n) { addedge(s, i, a[i], 0); addedge(i + n, t, a[i], 0); }
71     REP(i, 1, n) addedge(i, i + 1, inf, 0);
72     rep(i, 1, n) addedge(s, i + n, inf, P);
73     rep(i, 1, n) {
74         if (i + M <= n) addedge(i, i + M + n, inf, F);
75         if (i + N <= n) addedge(i, i + N + n, inf, S);
76     }
77     int ans(0);
78     pre[s] = -1;
79     while (spfa()) {
80         int flow = inf;
81         for (int i = pre[t]; i != -1; i = pre[E[i].u]) {
82             flow = min(flow, E[i].c);
83         }
84         for (int i = pre[t]; i != -1; i = pre[E[i].u]) {
85             E[i].c -= flow, E[i ^ 1].c += flow;
86             ans += flow * E[i].s;
87         }
88     }
89     printf("%d\n", ans);
90 }
View Code

 

  网络流24题 11 航空路线问题

    可以dp多线程。

    同样,拆点,一个点为入点,一个为出点。

    S到1的入点连接 【容量为2,费用为1】的边,n的出点连接 【容量为2,费用为0】的边,每条航线连接【容量为1,费用为1】的边,每个点出点到自己的入点连接【容量为1,费用为0】的边。(和第一个点和最后一个点相连的边容量均为2)。

    如果最大流不够,-1。

    因为要求最大费用最大流,所以把边权建成-1就好。

  1 #include <bits/stdc++.h>
  2 #define rep(i, a, b) for (int i = a; i <= b; i++)
  3 #define REP(i, a, b) for (int i = a; i < b; i++)
  4 #define drep(i, a, b) for (int i = a; i >= b; i--)
  5 #define clr(x) memset(x, 0, sizeof(x))
  6 #define pb push_back
  7 #define mp make_pair
  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 = 205, maxm = 10005;
 18 struct Ed {
 19     int u, v, nx, c, s; Ed() {}
 20     Ed(int _u, int _v, int _nx, int _c, int _s) :
 21         u(_u), v(_v), nx(_nx), c(_c), s(_s) {}
 22 } E[maxm << 1];
 23 int G[maxn], cnt;
 24 void addedge(int u, int v, int c, int s) {
 25     E[cnt] = Ed(u, v, G[u], c, s);
 26     G[u] = cnt++;
 27     E[cnt] = Ed(v, u, G[v], 0, -s);
 28     G[v] = cnt++;
 29 }
 30  
 31 int s, t, pre[maxn];
 32 int vis[maxn], dis[maxn];
 33 bool spfa() {
 34     static int que[maxm]; int qh(0), qt(0);
 35     clr(vis), memset(dis, 0x3f, sizeof(dis));
 36     vis[que[++qt] = s] = 1, dis[s] = 0;
 37     while (qh != qt) {
 38         int x = que[++qh]; vis[x] = 0;
 39         for (int i = G[x]; i != -1; i = E[i].nx) {
 40             if (E[i].c && dis[x] + E[i].s < dis[E[i].v]) {
 41                 pre[E[i].v] = i;
 42                 dis[E[i].v] = dis[x] + E[i].s;
 43                 if (!vis[E[i].v]) vis[que[++qt] = E[i].v] = 1;
 44             }
 45         }
 46     }
 47     return dis[t] != 0x3f3f3f3f;
 48 }
 49  
 50 map <string, int> M;
 51 string ch[maxn];
 52 int main() {
 53     int n, m;
 54     string str;
 55     cin >> n >> m;
 56     rep(i, 1, n) {
 57         cin >> str;
 58         ch[i] = str;
 59         M[str] = i;
 60     }
 61     s = 0, t = (n << 1) + 1;
 62     memset(G, -1, sizeof(G));
 63     addedge(s, 1, 2, -1), addedge(n << 1, t, 2, 0);
 64     while (m--) {
 65         int x, y;
 66         cin >> str; x = M[str];
 67         cin >> str; y = M[str];
 68         if (x == 1 || y == n) addedge(x, y + n, 2, -1);
 69         else addedge(x, y + n, 1, -1);
 70     }
 71     REP(i, 2, n) addedge(i + n, i, 1, 0);
 72     addedge(1 + n, 1, 2, 0), addedge(n + n, n, 2, 0);
 73     pre[0] = -1;
 74     int ans(0), f(0);
 75     while (spfa()) {
 76         int flow = inf;
 77         for (int i = pre[t]; i != -1; i = pre[E[i].u])
 78             flow = min(flow, E[i].c);
 79         f += flow;
 80         for (int i = pre[t]; i != -1; i = pre[E[i].u]) {
 81             E[i].c -= flow, E[i ^ 1].c += flow;
 82             ans += E[i].s * flow;
 83         }
 84     }
 85     if (f < 2) puts("-1");
 86     else {
 87         static int pri[maxn]; int top(0);
 88         cout << -ans - 2 << endl;
 89         int k = 1;
 90         while (1) {
 91             pri[++top] = k;
 92             for (int i = G[k]; i != -1; i = E[i].nx) {
 93                 if (E[i].v - n <= k) continue;
 94                 if (E[i ^ 1].c != 0) {
 95                     E[i].c += 1, E[i ^ 1].c -= 1;
 96                     k = E[i].v - n;
 97                     break;
 98                 }
 99             }
100             if (k == n) break;
101         }
102         k = n + n;
103         while (1) {
104             pri[++top] = k - n;
105             for (int i = G[k]; i != -1; i = E[i].nx) {
106                 if (E[i].v >= k - n) continue;
107                 if (E[i].c != 0) {
108                     k = E[i].v + n;
109                     break;
110                 }
111             }
112             if (k == n + 1) break;
113         }
114         pri[++top] = k - n;
115         for (int i = top; i >= 1; i--) cout << ch[pri[i]] << endl;
116     }
117     return 0;
118 }
View Code

 

posted @ 2015-11-23 16:26  y7070  阅读(297)  评论(0编辑  收藏  举报