最大流(多个源点,多个汇点) 之 poj 1274

//  [5/28/2014 Sjm]
/*
最大流:多个源点,多个汇点
// 若按二分图匹配做,请参见:http://www.cnblogs.com/shijianming/p/4140846.html
 
思路:
1)增加一个超级源点 S,从 S 向 每个源点 连一条容量为对应最大流出流量的边
2)增加一个超级汇点 T,从 每一个汇点 向 T 连一条容量为对应最大流入容量的边
 
对于此题:
源点 cows (范围:M+1 ~ M+N),汇点 stalls (范围:1 ~ M)
设 cows 与 the stalls (in which that cow is willing to produce milk)之间的容量为 1
1)设 0 为超级源点,
   因为每个 cow 流出的最大流出流量为 1(只能连一个stall),所以得:超级源点 向每个 cows 的连线的流量为 1
2)设 M+N+1 为超级汇点
   因为流入每个 stall 最大流量为 1(只能被一个cow连接),所以得:每个 stall 向 超级汇点 的连线的连线的流量为 1
 
*/
 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <cstdio>
 4 #include <vector>
 5 #include <algorithm>
 6 using namespace std;
 7 const int MAX_V = 410;
 8 const int INF = 0x3f3f3f3f;
 9 int N, M;
10 
11 struct edge { int to, cap, rev; };
12 vector<edge> G[MAX_V];
13 bool used[MAX_V];
14 
15 void add_edge(int from, int to, int cap)
16 {
17     edge e1 = { to, cap, G[to].size() };
18     G[from].push_back(e1);
19     edge e2 = { from, 0, G[from].size() - 1 };
20     G[to].push_back(e2);
21 }
22 
23 int dfs(int v, int t, int f)
24 {
25     if (v == t) return f;
26     used[v] = true;
27     for (int i = 0; i < G[v].size(); i++) {
28         edge &e = G[v][i];
29         if (!used[e.to] && (e.cap > 0)) {
30             int d = dfs(e.to, t, min(f, e.cap));
31             if (d > 0) {
32                 e.cap -= d;
33                 G[e.to][e.rev].cap += d;
34                 return d;
35             }
36         }
37     }
38     return 0;
39 }
40 
41 int Solve(int s, int t)
42 {
43     int flow = 0;
44     for (;;)
45     {
46         memset(used, 0, sizeof(used));
47         int f = dfs(s, t, INF);
48         if (!f) return flow;
49         flow += f;
50     }
51 }
52 
53 int main()
54 {
55     //freopen("input.txt", "r", stdin);
56     //freopen("output.txt", "w", stdout);
57     while (~scanf("%d %d", &N, &M))
58     {
59         for (int i = 1; i <= N; i++) {
60             int mycount;
61             scanf("%d", &mycount);
62             int tep;
63             for (int j = 0; j < mycount; j++) {
64                 scanf("%d", &tep);
65                 add_edge(M + i, tep, 1);
66             }
67         }
68         for (int i = 1; i <= N; i++) {
69             add_edge(0, M+i, 1);
70         }
71         for (int i = 1; i <= M; i++) {
72             add_edge(i, M + N + 1, 1);
73         }
74         printf("%d
", Solve(0, M + N + 1));
75         for (int i = 0; i < MAX_V; i++) {
76             G[i].clear();
77         }
78     }
79     return 0;
80 }
原文地址:https://www.cnblogs.com/shijianming/p/4140847.html