zoj 3642 Just Another Information Sharing Problem【最大流||多重匹配】

大意:

有n个熊孩子,,每个熊孩子有a个秘密,他最少愿意分享b个秘密, 最多愿意分享c个秘密, 接下来a个数表示这个熊孩子有的a个秘密的id

最后给一个熊孩子的编号m, 询问编号m最多能够知道多少个秘密

分析:

最大流, 但是询问的那个孩子的秘密就不用封印了,哈哈

也可以用二分图多重匹配, 而且时间快了一倍

代码:

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <vector>
  5 #include <queue>
  6 #include <map>
  7 using namespace std;
  8 
  9 const int maxn = 500 * 250 + 10;
 10 const int INF = 1000000000;
 11 
 12 struct Edge {
 13     int from, to, cap, flow;
 14 };
 15 
 16 struct Dinic {
 17     int n, m, s, t;
 18     vector<Edge> edges;
 19     vector<int>G[maxn];
 20     bool vis[maxn];
 21     int d[maxn];
 22     int cur[maxn];
 23 
 24     void ClearAll(int n) {
 25         for(int i = 0; i <= n; i++) {
 26             G[i].clear();
 27         }
 28         edges.clear();
 29     }
 30 
 31     void AddEdge(int from, int to, int cap) {
 32         edges.push_back((Edge) { from, to, cap, 0 } );
 33         edges.push_back((Edge) { to, from, 0, 0 } );
 34         m = edges.size();
 35         G[from].push_back(m - 2);
 36         G[to].push_back(m - 1);
 37     }
 38 
 39     bool BFS()
 40     {
 41         memset(vis, 0, sizeof(vis) );
 42         queue<int> Q;
 43         Q.push(s);
 44         vis[s] = 1;
 45         d[s] = 0;
 46         while(!Q.empty() ){
 47             int x = Q.front(); Q.pop();
 48             for(int i = 0; i < G[x].size(); i++) {
 49                 Edge& e = edges[G[x][i]];
 50                 if(!vis[e.to] && e.cap > e.flow) {
 51                     vis[e.to] = 1;
 52                     d[e.to] = d[x] + 1;
 53                     Q.push(e.to);
 54                 }
 55             }
 56         }
 57         return vis[t];
 58     }
 59 
 60     int DFS(int x, int a) {
 61         if(x == t || a == 0) return a;
 62         int flow = 0, f;
 63         for(int& i = cur[x]; i < G[x].size(); i++) {
 64             Edge& e = edges[G[x][i]];
 65             if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
 66                 e.flow += f;
 67                 edges[G[x][i]^1].flow -= f;
 68                 flow += f;
 69                 a -= f;
 70                 if(a == 0) break;
 71             }
 72         }
 73         return flow;
 74     }
 75 
 76     int MaxFlow(int s, int t) {
 77         this -> s = s; this -> t = t;
 78         int flow = 0;
 79         while(BFS()) {
 80             memset(cur, 0, sizeof(cur));
 81             flow += DFS(s, INF);
 82         }
 83         return flow;
 84     }
 85 };
 86 
 87 Dinic g;
 88 
 89 map<int, int> mp;
 90 int a[maxn], b[maxn], c[maxn];
 91 int A[55][205];
 92 
 93 int n, m, num, tot;
 94 int s, t;
 95 
 96 int main() {
 97     while(EOF != scanf("%d",&n) ) {
 98         for(int i = 1; i <= n; i++) {
 99             scanf("%d %d %d",&a[i], &b[i], &c[i]);
100             for(int j = 1; j <= a[i]; j++) {
101                 scanf("%d",&A[i][j]);
102             }
103         }
104         scanf("%d",&m);
105         mp.clear();
106         g.ClearAll(n * (n + 200) );
107         s = 0; t = n + 200 + 1;
108         int tot = n + 1;
109         for(int i = 1; i <= n; i++) {
110             if(i != m) {
111                 g.AddEdge(s, i, c[i]);
112             } else {
113                 g.AddEdge(s, i, a[i]);
114             }
115             for(int j = 1; j <= a[i]; j++) {
116                 num = A[i][j];
117                 if(!mp[num]) mp[num] = tot++;
118                 g.AddEdge(i, mp[num], 1);
119             }
120         }
121         for(int i = n + 1; i < tot; i++) {
122             g.AddEdge(i, t, 1);
123         }
124         printf("%d
", g.MaxFlow(s, t));
125     }
126     return 0;
127 }
View Code
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 #include <map>
 6 using namespace std;
 7 
 8 const int maxn = 205;
 9 
10 int cap[maxn];
11 int Link[maxn][maxn];
12 int vLink[maxn];
13 int mat[maxn][maxn];
14 int vis[maxn];
15 int n, m;
16 
17 bool Find(int u) {
18     for(int i = 1; i <= m; i++) {
19         if(!vis[i] && mat[u][i]) {
20             int v = i;
21             vis[v] = 1;
22             if(vLink[v] < cap[v]) {
23                 Link[v][vLink[v]++] = u;
24                 return true;
25             }
26             for(int j = 0; j < vLink[v]; j++) {
27                 if(Find(Link[v][j])) {
28                     Link[v][j] = u;
29                     return true;
30                 }
31             }
32         }
33     }
34     return false;
35 }
36 
37 int solve() {
38     int cnt = 0;
39     memset(Link, 0, sizeof(Link));
40     memset(vLink, 0, sizeof(vLink));
41     for(int i = 1; i <= n; i++) {
42         memset(vis, 0, sizeof(vis));
43         if(Find(i) ) cnt ++;
44     }
45     return cnt;
46 }
47 
48 int a[maxn], b[maxn], c[maxn];
49 int A[maxn][maxn];
50 map<int, int> mp;
51 
52 int main() {
53     int x, y;
54     while(EOF != scanf("%d",&x) ) {
55         for(int i = 1; i <= x; i++) {
56             scanf("%d %d %d", &a[i], &b[i], &c[i]);
57             for(int j = 1; j <= a[i]; j++) {
58                 scanf("%d",&A[i][j]);
59             }
60         }
61         scanf("%d",&y);
62         mp.clear();
63         memset(mat, 0, sizeof(mat));
64         int tot = 1;
65         for(int i = 1; i <= x; i++) {
66             cap[i] = c[i];
67             for(int j = 1; j <= a[i]; j++) {
68                 int num = A[i][j];
69                 if(!mp[num]) mp[num] = tot++;
70                 mat[mp[num]][i] = 1;
71             }
72         }
73         cap[y] = a[y];
74         n = tot - 1; m = x;
75         printf("%d
", solve());
76     }
77     return 0;
78 }
多重匹配
原文地址:https://www.cnblogs.com/zhanzhao/p/3965143.html