HDU 3081 Marriage Match II(最大流 + 并查集)
来源:互联网 发布:好玩的java web项目 编辑:程序博客网 时间:2024/05/17 01:47
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3081
题意:给出每个女生能配对的男生,再给出每个女生的朋友,朋友关系能传递,每个女生也能和她朋友的男朋友配对,每次配对女生都要和不同的男生配对,问最多能配对多少轮
思路:先用并查集处理女生间的关系,再二分答案,源点向女生连边容量为mid,女生向其能匹配的男生连边容量为1,每个男生再向汇点连边容量为mid,这样如果能满流就证明能进行mid轮的配对
也可以用二分图匹配,每次匹配后将匹配边拆掉,重复该过程直至匹配数不为最大匹配为止
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <utility>#include <cmath>#include <queue>#include <set>#include <map>#include <climits>#include <functional>#include <deque>#include <ctime>#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;typedef long long ll;const int MAXN = 300;const int MAXM = 100010;const int INF = 0x3f3f3f3f;struct Edge{ int to, next, cap, flow;} edge[MAXM];int tol;int Head[MAXN];int gap[MAXN], dep[MAXN], cur[MAXN];void init(){ tol = 0; memset(Head, -1, sizeof(Head));}void addedge(int u, int v, int w, int rw = 0){ edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; edge[tol].next = Head[u]; Head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; edge[tol].next = Head[v]; Head[v] = tol++;}int Q[MAXN];void BFS(int start, int end){ memset(dep, -1, sizeof(dep)); memset(gap, 0, sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; dep[end] = 0; Q[rear++] = end; while (front != rear) { int u = Q[front++]; for (int i = Head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (dep[v] != -1)continue; Q[rear++] = v; dep[v] = dep[u] + 1; gap[dep[v]]++; } }}int S[MAXN];int sap(int start, int end, int N){ BFS(start, end); memcpy(cur, Head, sizeof(Head)); int top = 0; int u = start; int ans = 0; while (dep[start] < N) { if (u == end) { int Min = INF; int inser; for (int i = 0; i < top; i++) if (Min > edge[S[i]].cap - edge[S[i]].flow) { Min = edge[S[i]].cap - edge[S[i]].flow; inser = i; } for (int i = 0; i < top; i++) { edge[S[i]].flow += Min; edge[S[i] ^ 1].flow -= Min; } ans += Min; top = inser; u = edge[S[top] ^ 1].to; continue; } bool flag = false; int v; for (int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u]) { flag = true; cur[u] = i; break; } } if (flag) { S[top++] = cur[u]; u = v; continue; } int Min = N; for (int i = Head[u]; i != -1; i = edge[i].next) if (edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if (!gap[dep[u]])return ans; dep[u] = Min + 1; gap[dep[u]]++; if (u != start)u = edge[S[--top] ^ 1].to; } return ans;}int n, m, f;int l[MAXM], r[MAXM], fa[MAXN], g[MAXN][MAXN];int Find(int x){ if (x == fa[x]) return x; return fa[x] = Find(fa[x]);}void unite(int x, int y){ x = Find(x), y = Find(y); if (x == y) return ; fa[x] = y;}bool solve(int mid){ init(); memset(g, 0, sizeof(g)); int s = 0, t = n * 2 + 1; for (int i = 1; i <= n; i++) { addedge(s, i, mid); addedge(i + n, t, mid); } for (int i = 0; i < m; i++) { int u = l[i], v = r[i]; for (int j = 1; j <= n; j++) { if (Find(u) == Find(j) && !g[j][v]) { g[j][v] = 1; addedge(j, v + n, 1); } } } int flow = sap(s, t, t + 1); return flow == mid * n ? true : false;}int main(){ int t; cin >> t; while (t--) { scanf("%d%d%d", &n, &m, &f); for (int i = 0; i <= n; i++) fa[i] = i; for (int i = 0; i < m; i++) scanf("%d%d", &l[i], &r[i]); for (int i = 0; i < f; i++) { int u, v; scanf("%d%d", &u, &v); unite(u, v); } int L = 0, R = n, ans = 0; while (L <= R) { int mid = (L + R) >> 1; if (solve(mid)) L = mid + 1, ans = max(ans, mid); else R = mid - 1; } cout << ans << endl; } return 0;}
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <utility>#include <cmath>#include <queue>#include <set>#include <map>#include <climits>#include <functional>#include <deque>#include <ctime>#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;typedef long long ll;const int MAXN = 300;const int MAXM = 100010;const int INF = 0x3f3f3f3f;int uN, vN;int g[MAXN][MAXN];int linker[MAXN];bool used[MAXN];bool dfs(int u){ for (int v = 1; v <= vN; v++) if (g[u][v] && !used[v]) { used[v] = true; if (linker[v] == -1 || dfs(linker[v])) { linker[v] = u; return true; } } return false;}int hungary(){ int res = 0; memset(linker, -1, sizeof(linker)); for (int u = 1; u <= uN; u++) { memset(used, false, sizeof(used)); if (dfs(u)) res++; } return res;}int n, m, f;int l[MAXM], r[MAXM], fa[MAXN];int Find(int x){ if (x == fa[x]) return x; return fa[x] = Find(fa[x]);}void unite(int x, int y){ x = Find(x), y = Find(y); if (x == y) return ; fa[x] = y;}int main(){ int t; cin >> t; while (t--) { scanf("%d%d%d", &n, &m, &f); for (int i = 0; i <= n; i++) fa[i] = i; for (int i = 0; i < m; i++) scanf("%d%d", &l[i], &r[i]); for (int i = 0; i < f; i++) { int u, v; scanf("%d%d", &u, &v); unite(u, v); } uN = n, vN = n; memset(g, 0, sizeof(g)); for (int i = 0; i < m; i++) g[Find(l[i])][r[i]] = 1; for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) if (g[Find(i)][j]) g[i][j] = 1; int ans = 0; while (true) { int res = hungary(); if (res != n) break; ans++; for (int i = 1; i <= n; i++) g[linker[i]][i] = 0; } cout << ans << endl; } return 0;}
0 0
- 并查集+最大流-HDU-3038-Marriage Match II
- hdu 3081 Marriage Match II(二分最大流+并查集+判断满流)
- HDU 3081Marriage Match II(二分+并查集+网络流之最大流)
- hdu 3081 Marriage Match II(最大流 + 二分 + 并查集)
- 【HDU】 3081 Marriage Match II (最大流+并查集)
- HDU 3081 Marriage Match II(最大流 + 并查集)
- hdu 3081 Marriage Match II (二分+最大流+并查集)
- HDU-3081-Marriage Match II(最大流+并查集+二分)
- hdu 3081 Marriage Match II(二分, 并查集,最大流)
- HDU - 3081 Marriage Match II(最大流+并查集+二分查找)
- hdu 3081 Marriage Match II 【图论-网络流-最大流+并查集】
- HDU 3081 Marriage Match II —并查集,最大流
- HDU 3081 Marriage Match II(二分+并查集+最大流)
- HDU 3081 Marriage Match II [二分最大流]+并查集?807★
- HDU 3081 Marriage Match II(二分+并查集+最大流)
- hdu 3081 Marriage Match II【并查集+二分+最大流Dinic+建图】
- HDU 3081 Marriage Match II(二分+并查集+最大流)
- HUD -- 3081 Marriage Match II(最大流+二分+并查集)
- CF 91E
- oop_day01_类和对象_20150807
- 求最大子序列和--体会算法的魅力
- 14、C语言和设计模式(装饰模式)
- C语言中的逻辑运算符
- HDU 3081 Marriage Match II(最大流 + 并查集)
- struct的初始化及其构造函数
- iOS-为视图添加阴影
- JAVA在ACM中的几点应用
- 数论 - 线性筛法与积性函数
- JAVA接口的用法
- hdu-4127 Flood-it!(IDA*算法)
- 黑马程序员--- objective-c 封装 set与get
- 字符串处理