二分图'多重匹配'

// 模板。(匈牙利的稍微改写) 和 例题(最下面) 一般多重匹配需要配合二分查找答案

// 例题 :hdu 3605

// 题意:有n(n <= 100000)个人和m(m <= 10)个星球,  每个人有自己想去的星球(不止一个), 但每个星球能承受的人数不同。问: 能不能把所有人安排到他自己想去的星球上;

// 输入(机翻): 

 

 //输出 YES or NO

 1 #include<iostream>
 2 #define read(n) n = read_n()
 3 #define rep(i, n) for(int i=0;i!=n;++i)
 4 #define rep1(i, n) for(int i=1;i<=n;++i)
 5 using namespace std;
 6 
 7 inline int read_n() {
 8     char c=getchar();int x=0,f=1;
 9     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
10     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
11     return x*f;
12 }
13 // -----------------------------------------------------
14 const int MAXN = 100000+5;
15 const int MAXM = 10+5;
16 const int MAXE = MAXN*MAXM;
17 
18 int num;
19 int head[MAXN];
20 struct node {
21     int v, next;
22 } edge[MAXE];
23 
24 inline void add(int x, int y) {
25     edge[num].v = y;
26     edge[num].next = head[x];
27     head[x] = num++;
28 }
29 
30 int n, m;
31 int maxn[MAXM];
32 
33 int cnt[MAXM];
34 int love[MAXM][MAXN];// love[i][j]表示i星球的第j位置匹配到了某人
35 bool vis[MAXM];
36 // -----------------核心----------------------
37 bool dfs(int u) {
38     for(int i = head[u]; i != -1; i = edge[i].next) {
39         int v = edge[i].v;
40         if(!vis[v]) {
41             vis[v] = true;
42             if(cnt[v] < maxn[v]) {// 如果v还有"位置"匹配
43                 love[v][++cnt[v]] = u;
44                 return true;
45             }
46             for(int j = 1; j <= cnt[v]; ++j) {// 若没有位置了, 从已经匹配的上面找是否有人能腾出位置
47                 if(dfs(love[v][j])) {
48                     love[v][j] = u;
49                     return true;
50                 }
51             }
52         }
53     }
54     return false;
55 }
56 // ---------------------------------------------
57 bool solve() {
58     rep1(i, m) cnt[i] = 0;
59     rep1(i, n) {
60         rep1(j, m) vis[j] = false;
61         if(!dfs(i)) return false;
62     }
63     return true;
64 }
65 
66 int main() {
67     while(cin >> n >> m) {
68         num = 0;
69         rep1(i, n) head[i] = -1;
70         int x;
71         rep1(i, n) rep1(j, m) {
72             read(x);
73             if(x == 1) add(i, j);
74         }
75         rep1(i, m) read(maxn[i]);
76         if(solve()) cout << "YES\n";
77         else cout << "NO\n";
78     }
79     return 0;
80 }

 // poj 2289 二分查找答案

 1 #include<iostream>
 2 #include<sstream>
 3 #include<cstdlib>
 4 using namespace std;
 5 
 6 const int MAXN = 1000+5;
 7 const int MAXM = 500+5;
 8 const int MAXE = MAXN*MAXM;
 9 
10 int num;
11 int head[MAXN];
12 struct node {
13     int v, next;
14 } edge[MAXE];
15 
16 inline void add(int x, int y) {
17     edge[num].v = y;
18     edge[num].next = head[x];
19     head[x] = num++;
20 }
21 
22 int n, m, maxn;
23 string str;
24 
25 int cnt[MAXN];
26 int love[MAXN][MAXM];
27 bool vis[MAXN];
28 
29 bool dfs(int u) {
30     for(int i = head[u]; i != -1; i = edge[i].next) {
31         int v = edge[i].v;
32         if(!vis[v]) {
33             vis[v] = true;
34             if(cnt[v] < maxn) {
35                 love[v][++cnt[v]] = u;
36                 return true;
37             }
38             for(int j = 1; j <= cnt[v]; ++j) {
39                 if(dfs(love[v][j])) {
40                     love[v][j] = u;
41                     return true;
42                 }
43             }
44         }
45     }
46     return false;
47 }
48 
49 bool hungry(int p) {
50     maxn = p;
51     for(int i = 0; i != m; ++i) cnt[i] = 0;
52     for(int i = 1; i <= n; ++i) {
53         for(int j = 0; j != m; ++j) vis[j] = false;
54         if(!dfs(i)) return false;
55     }
56     return true;
57 }
58 
59 int main() {
60     ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
61     while(cin >> n >> m && n) {
62         num = 0;
63         getchar();
64         for(int i = 1; i <= n; ++i) head[i] = -1;
65         for(int i = 1; i <= n; ++i) {
66             getline(cin, str);
67             stringstream s(str);
68             string ss;
69             while(s >> ss) {
70                 if(isalpha(ss[0])) continue;
71                 int p = atoi(ss.c_str());
72                 add(i, p);
73             }
74         }
75         int l = 1, r = n, mid, ans;
76         while(l <= r) {
77             mid = (l+r)/2;
78             if(hungry(mid)) ans = mid, r = mid - 1;
79             else l = mid + 1;
80         }
81         cout << ans << "\n";
82     }
83     return 0;
84 }
View Code

// poj 2112 二分查找答案

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<vector>
 4 #define rep(i, n) for(int i=0;i!=n;++i)
 5 #define rep1(i, n) for(int i=1;i<=n;++i)
 6 #define Rep1(i, sta, n) for(int i=sta;i<=n;++i)
 7 using namespace std;
 8 // -----------------------------------------------------
 9 const int MAXN = 230+5;
10 const int MAXE = MAXN*MAXN;
11 
12 int num;
13 int head[MAXN];
14 struct node {
15     int v, next;
16 } edge[MAXE];
17 
18 inline void add(int x, int y) {
19     edge[num].v = y;
20     edge[num].next = head[x];
21     head[x] = num++;
22 }
23 
24 int n, m, nm, maxn, dis;
25 int G[MAXN][MAXN];
26 
27 int cnt[MAXN];
28 int love[MAXN][MAXN];
29 bool vis[MAXN];
30 
31 bool dfs(int u) {
32     for(int i = head[u]; i != -1; i = edge[i].next) {
33         int v = edge[i].v;
34         if(G[u][v] > dis) continue;
35         if(!vis[v]) {
36             vis[v] = true;
37             if(cnt[v] < maxn) {
38                 love[v][++cnt[v]] = u;
39                 return true;
40             }
41             for(int j = 1; j <= cnt[v]; ++j) {
42                 if(dfs(love[v][j])) {
43                     love[v][j] = u;
44                     return true;
45                 }
46             }
47         }
48     }
49     return false;
50 }
51 
52 bool solve(int d) {
53     dis = d;
54     rep1(i, m) cnt[i] = 0;
55     Rep1(i, m+1, nm) {
56         rep1(j, m) vis[j] = false;
57         if(!dfs(i)) return false;
58     }
59     return true;
60 }
61 
62 int main() {
63     ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
64     cin >> m >> n >> maxn;
65     nm = n+m;
66     num = 0;
67     rep1(i, nm) head[i] = -1;
68     rep1(i, nm) rep1(j, nm) cin >> G[i][j];
69     rep1(k, nm) {
70         rep1(i, nm) {
71             if(G[i][k]) rep1(j, nm) if(G[k][j]) if(!G[i][j] || G[i][k]+G[k][j] < G[i][j]) {
72                 G[i][j] = G[i][k] + G[k][j];
73             }
74         }
75     }
76     vector<int> v;
77     Rep1(i, m+1, nm) {
78         Rep1(j, 1, m) if(G[i][j]) add(i, j), v.push_back(G[i][j]);
79     }
80     sort(v.begin(), v.end());
81     int l = 0, r = unique(v.begin(), v.end()) - v.begin()-1;
82     int mi, ans;
83     while(l <= r) {
84         mi = (l+r)>>1;
85         if(solve(v[mi])) ans = v[mi], r = mi-1;
86         else l = mi+1;
87     }
88     cout << ans << "\n";
89     return 0;
90 }
View Code

// poj 3189 二分+枚举约束条件找答案

 1 /*
 2  * @Promlem: 
 3  * @Time Limit: ms
 4  * @Memory Limit: k
 5  * @Author: pupil-XJ
 6  * @Date: 2019-11-04 23:50:39
 7  * @LastEditTime: 2019-11-05 00:27:17
 8  */
 9 #include<cstdio>
10 using namespace std;
11 const int MAXN = 1000+5;
12 const int MAXM = 20+5;
13 const int MAXE = MAXN*MAXM;
14 
15 int num;
16 int head[MAXN];
17 struct node {
18     int v, w, next;
19 } edge[MAXE];
20 
21 inline void add(int x, int y, int w) {
22     edge[num].v = y;
23     edge[num].w = w;
24     edge[num].next = head[x];
25     head[x] = num++;
26 }
27 
28 int n, m;
29 int G[MAXN][MAXM];
30 int maxn[MAXM];
31 
32 int cnt[MAXM];
33 int love[MAXM][MAXN];
34 bool vis[MAXM];
35 
36 bool dfs(int u, int l, int r) {
37     for(int i = head[u]; i != -1; i = edge[i].next) {
38         int v = edge[i].v;
39         if(edge[i].w < l || edge[i].w > r) continue;
40         if(!vis[v]) {
41             vis[v] = true;
42             if(cnt[v] < maxn[v]) {
43                 love[v][++cnt[v]] = u;
44                 return true;
45             }
46             for(int j = 1; j <= cnt[v]; ++j) {
47                 if(dfs(love[v][j], l, r)) {
48                     love[v][j] = u;
49                     return true;
50                 }
51             }
52         }
53     }
54     return false;
55 }
56 
57 bool solve(int l, int r) {
58     for(int i = 1; i <= m; ++i) cnt[i] = 0;
59     for(int i = 1; i <= n; ++i) {
60         for(int j = 1; j <= m; ++j) vis[j] = false;
61         if(!dfs(i, l, r)) return false;
62     }
63     return true;
64 }
65 
66 int main() {
67     scanf("%d%d", &n, &m);
68     num = 0;
69     for(int i = 1; i <= n; ++i) head[i] = -1;
70     for(int i = 1; i <= n; ++i) {
71         for(int j = 1; j <= m; ++j) {
72             scanf("%d", &G[i][j]);
73             add(i, G[i][j], j);
74         }
75     }
76     for(int i = 1; i <= m; ++i) scanf("%d", &maxn[i]);
77     int l = 1, r = m;
78     int mid, ans;
79     while(l <= r) {
80         bool flag = false;
81         mid = (l+r)>>1;
82         for(int i = 1; i+mid-1<=m; ++i) {
83             if(solve(i, i+mid-1)) ans = mid, flag = true;
84             if(flag) break;
85         }
86         if(flag) r = mid-1;
87         else l = mid+1;
88     }
89     printf("%d\n", ans);
90     return 0;
91 }
View Code

 

posted @ 2019-11-04 16:35  pupil337  阅读(181)  评论(0编辑  收藏  举报