您的位置:首页 > 其它

hdu3081 Marriage Match II

2016-02-03 22:27 501 查看
题目大意就是有n对男女,玩儿结婚游戏,要求就是开始每个女生心目中都会有几个心仪的男生,同时呢,好友(girl)心仪的男生也是可以选做自己的boyfriend。每一轮游戏男女配对(只和心仪的)且不于之前配对过的配对,问最多可以玩儿几轮这样的游戏。

男女配对显然是二分图,然后就是二分次数k,k必然是大于1而小于n+1的。

/*****************************************
Author      :Crazy_AC(JamesQi)
Time        :2015
File Name   :
*****************************************/
// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <climits>
using namespace std;
#define MEM(x,y) memset(x, y,sizeof x)
#define pk push_back
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef pair<ii,int> iii;
const double eps = 1e-10;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 110;
int g

;
int n, m, f;
int F
;
int Find(int x) {return F[x] == -1?x:F[x] = Find(F[x]);}
void input() {
memset(g, 0,sizeof g);
scanf("%d%d%d",&n,&m,&f);
int u, v;
for (int i = 1;i <= m;++i) {
scanf("%d%d",&u,&v);
g[u][v] = 1;
}
memset(F, -1,sizeof F);
for (int i = 1;i <= f;++i) {
scanf("%d%d",&u,&v);
int t1 = Find(u),t2 = Find(v);
if (t1 != t2) F[t1] = t2;
}
for (int i = 1;i <= n;++i) {
for (int j = 1;j <= n;++j) {
int t1 = Find(i),t2 = Find(j);
if (t1 == t2) {
for (int k = 1;k <= n;++k)
g[i][k] |= g[j][k];
}
}
}
}
int head[N*3], pnt[N*1000], nxt[N*1000], cap[N*1000], flow[N*1000];
int cnt;
int cur[N*3];
int dis[N*3];
void addedge(int u,int v,int can) {
pnt[cnt] = v,cap[cnt] = can, flow[cnt] = 0;
nxt[cnt] = head[u], head[u] = cnt++;

pnt[cnt] = u,cap[cnt] = 0,flow[cnt] = 0;
nxt[cnt] = head[v], head[v] = cnt++;
}
bool bfs(int s,int t) {
queue<int> que;
que.push(s);
memset(dis, -1,sizeof dis);
dis[s] = 0;
while(!que.empty()) {
int u = que.front();
que.pop();
for (int i = head[u];i!=-1;i = nxt[i]) {
if (dis[pnt[i]] == -1 && cap[i] > flow[i]) {
dis[pnt[i]] = dis[u] + 1;
que.push(pnt[i]);
}
}
}
return dis[t] != -1;
}
int dfs(int u,int a,int t) {
if (u == t || a == 0) return a;
int sum = 0;
for (int &i = cur[u];~i;i = nxt[i]) {
int v = pnt[i];
int f;
if (dis[v] == dis[u] + 1 && (f = dfs(v, min(a, cap[i] - flow[i]), t)) > 0) {
sum += f;
flow[i] += f;
flow[i^1] -= f;
a -= f;
if (a == 0) break;
}
}
return sum;
}
int MaxFlow(int s,int t) {
int sum = 0;
while(bfs(s, t)) {
memcpy(cur, head, sizeof head);
sum += dfs(s, INF, t);
}
return sum;
}
void getmap(int mid) {
memset(head, -1,sizeof head);
cnt = 0;
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 j = 1;j <= n;++j) {
if (g[i][j]) addedge(i, j+n, 1);
}
}
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int t;
scanf("%d",&t);
while(t--) {
input();
int low = 1,high = n + 1;
int ans = -1;
while(low < high) {
int mid = (low + high) / 2;
getmap(mid);
int tmp = MaxFlow(0,n*2+1);
if (tmp == n*mid) {
low = mid + 1;
}else high = mid;
}
printf("%d\n", low - 1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: