【二分图多重匹配 && Dinic】POJ - 2289 Jamie's Contact Groups
2017-11-12 19:44
471 查看
Problem Description
给你m个组别,每个组别可以只能放特定的人。并最大限度地减少最大组的人数
思路:
0-(m-1)代表人,m代表超级源点,n-(n+m)代表组别,n+m+1代表超级汇点。二分 人到超级汇点的流量,最大流求最大匹配,如果最大匹配 = n就减少流量。
给你m个组别,每个组别可以只能放特定的人。并最大限度地减少最大组的人数
思路:
0-(m-1)代表人,m代表超级源点,n-(n+m)代表组别,n+m+1代表超级汇点。二分 人到超级汇点的流量,最大流求最大匹配,如果最大匹配 = n就减少流量。
#include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; #define N 1005 #define M 505 #define inf 0x3f3f3f3f struct node { int to, cap, next; }; node Map[2*N*M]; vector<int> a ; int n, m, cnt; int head[N+M], vis[N+M]; bool bfs(int s, int e) { memset(vis, -1, sizeof(vis)); queue<int> q; q.push(s); vis[s] = 0; while(!q.empty()) { s = q.front(), q.pop(); for(int i = head[s]; ~i; i = Map[i].next) { int to = Map[i].to, cap = Map[i].cap; if(cap && vis[to] == -1) { vis[to] = vis[s] + 1; q.push(to); } } } if(vis[e] == -1) return 0; else return 1; } int dfs(int s, int e, int f) { if(s == e) return f; int ans = 0; for(int i = head[s]; ~i; i = Map[i].next) { int to = Map[i].to, &cap = Map[i].cap; if(vis[to] > vis[s] && cap) { int d = dfs(to, e, min(f, cap)); if(d) { cap -= d; Map[i^1].cap += d; f -= d; ans += d; if(!f) break; } } } if(ans) return ans; vis[s] = -1; return 0; } int dinic(int s, int e) { int ans = 0; while(bfs(s, e)) { ans += dfs(s, e, inf); } return ans; } void add(int u, int v, int cap) { Map[cnt].to = v; Map[cnt].cap = cap; Map[cnt].next = head[u]; head[u] = cnt++; Map[cnt].to = u; Map[cnt].cap = 0; Map[cnt].next = head[v]; head[v] = cnt++; } void build(int mid)//m是源点 n+m+1是汇点 { int i, j; memset(head, -1, sizeof(head)); cnt = 0; for(i = 1; i <= n; i++) { add(m, i+m, 1);//超级源点->组别 for(j = 0; j < a[i].size(); j++) { add(i+m, a[i][j], 1);//组别->人 } } for(i = 0; i < m; i++) { add(i, n+m+1, mid);//人->超级汇点 } } int main() { char s[20]; int num; while(~scanf("%d %d", &n, &m) && n+m) { for(int i = 1; i <= n; i++) { a[i].clear(); scanf("%s", s); while(getchar() != '\n') { scanf("%d", &num); a[i].push_back(num); } } int l = 1, r = n; while(l <= r) { int mid = (l + r) / 2; build(mid);//对于每个人到超级汇点的流量,重新建边 if(dinic(m, n+m+1) == n) r = mid - 1;//求最大流 else l = mid + 1; } printf("%d\n", r + 1); } return 0; }
相关文章推荐
- POJ 2289 Jamie’s Contact Groups-二分匹配&多重匹配
- POJ2289 Jamie's Contact Groups(二分图多重匹配)
- POJ2289-Jamie's Contact Groups(二分图多重匹配)
- POJ 2289 Jamie's Contact Groups (二分答案+二分图的多重匹配)
- poj2289--Jamie's Contact Groups(二分多重匹配)
- POJ 2289 Jamie's Contact Groups (二分+dinic)
- Poj 2289 Jamie's Contact Groups【二分+多重匹配】
- POJ -2289 -Jamie's Contact Groups (二分图多重匹配)
- POJ 2289 Jamie's Contact Groups (二分答案+匹配流)
- POJ 2289 Jamie's Contact Groups 多重匹配+二分
- poj 2289 Jamie's Contact Groups 【二分 + 最大流】
- POJ 2289--Jamie's Contact Groups【二分图多重匹配问题 &&二分查找最大值的最小化 && 最大流求解】
- HDU1669 Jamie's Contact Groups 二分法+二分图的多重匹配
- poj2289 Jamie's Contact Groups(二分答案+最大流)
- Jamie's Contact Groups POJ - 2289
- Poj-2289 Jamie's Contact Groups 多重二分图匹配
- POJ2289 Jamie's Contact Groups(二分图多重匹配+二分)
- POJ 2289——Jamie's Contact Groups——————【多重匹配、二分枚举匹配次数】
- Poj 2289 Jamie's Contact Groups 【最大流Dinic+二分】
- Jamie's Contact Groups (二分图多重匹配)