题目链接:https://vjudge.net/problem/HDU-3081

Marriage Match II

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4493    Accepted Submission(s): 1488

Problem Description
Presumably, you all have known the question of stable marriage match. A girl will choose a boy; it is similar as the game of playing house we used to play when we are kids. What a happy time as so many friends playing together. And it is normal that a fight or a quarrel breaks out, but we will still play together after that, because we are kids. 
Now, there are 2n kids, n boys numbered from 1 to n, and n girls numbered from 1 to n. you know, ladies first. So, every girl can choose a boy first, with whom she has not quarreled, to make up a family. Besides, the girl X can also choose boy Z to be her boyfriend when her friend, girl Y has not quarreled with him. Furthermore, the friendship is mutual, which means a and c are friends provided that a and b are friends and b and c are friend. 
Once every girl finds their boyfriends they will start a new round of this game—marriage match. At the end of each round, every girl will start to find a new boyfriend, who she has not chosen before. So the game goes on and on.
Now, here is the question for you, how many rounds can these 2n kids totally play this game?
 
Input
There are several test cases. First is a integer T, means the number of test cases. 
Each test case starts with three integer n, m and f in a line (3<=n<=100,0<m<n*n,0<=f<n). n means there are 2*n children, n girls(number from 1 to n) and n boys(number from 1 to n).
Then m lines follow. Each line contains two numbers a and b, means girl a and boy b had never quarreled with each other. 
Then f lines follow. Each line contains two numbers c and d, means girl c and girl d are good friends.
 
Output
For each case, output a number in one line. The maximal number of Marriage Match the children can play.
 
Sample Input
1
4 5 2
1 1
2 3
3 2
4 2
4 4
1 4
2 3
 
Sample Output
2
 
Author
starvae
 
Source
 
Recommend
lcy

题意:

有n个女生和n个男生,有两种关系:1)女生a与男生b没有吵过架, 2)女生a与女生b是朋友。并且朋友关系是互相的且可以传递的(注意:只有女生才拥有朋友关系,男生没有这一个概念)。接着女生挑选男生作为男朋友,可以挑选和她没有吵过架的或者没有跟她朋友吵过架的男生。当所有女生都选完男朋友之后,一轮结束,再进行下一轮匹配挑选,规定选择过的伴侣不能再选。问:最多能进行多少轮匹配?

传递闭包 + 最大匹配:

1.根据题目意思,可以先用Flyod算法求出传递闭包。

2.由于在每一轮的匹配中,每个女生都要求能够找到男朋友。所以我们可以建立二分图,求出最大匹配是否完全匹配。

3.如果第2步中求出的是完全匹配,那么表示这一轮的匹配是有效的。由于题目要求新一轮的匹配中,不能选择“前任”,那么我们就把这一轮所有匹配对断开关系,即去掉两者之间的边。然后重复第2步。直到求出的不是完全匹配。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int MAXM = 1e5+;
const int MAXN = 2e2+; int uN, vN;
int maze[MAXN][MAXN], id[MAXN][MAXN], link[MAXN];
bool vis[MAXN]; bool dfs(int u)
{
for(int i = uN+; i<=uN+vN; i++)
if(maze[u][i] && !vis[i])
{
vis[i] = true;
if(link[i]==- || dfs(link[i]))
{
link[i] = u;
return true;
}
}
return false;
} bool hungary()
{
int ret = ;
memset(link, -, sizeof(link));
for(int i = ; i<=uN; i++)
{
memset(vis, , sizeof(vis));
if(!dfs(i)) return false;
}
return true;
} void flyod(int N)
{
for(int k = ; k<=N; k++)
for(int i = ; i<=N; i++)
for(int j = ; j<=N; j++)
maze[i][j] = maze[i][j]||(maze[i][k]&&maze[k][j]);
} int main()
{
int T, n, m, f;
scanf("%d", &T);
while(T--)
{
scanf("%d%d%d", &n,&m,&f);
uN = vN = n;
memset(maze, , sizeof(maze));
for(int i = ; i<=m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
maze[u][uN+v] = ;
}
for(int i = ; i<=f; i++)
{
int u, v;
scanf("%d%d", &u, &v);
maze[u][v] = maze[v][u] = ;
} flyod(uN+vN);
int round = ;
while(hungary())
{
round++;
for(int i = uN+; i<=uN+vN; i++)
maze[link[i]][i] = ;
}
printf("%d\n", round);
}
}

传递闭包 + 二分 + 最大流:

1.同样,先用Flyod算法求出传递闭包。

2.二分答案,即轮数,然后检测是否合法,以此缩小范围,最终得出最优解。

3.怎么检测是否合法呢?答:利用最大流算法进行检测:

  1) 建立超级源点,超级源点连向每个女生,边权为二分的轮数mid,表明这个女生要有过mid个男朋友;

  2) 建立超级汇点,每个男生连向超级汇点,且边权也为mid,表明这个男生要有mid个女朋友;

  3) 然后如果女生girl能挑选男生boy,那么就连一条边u-->v,边权为1,表明,该男女只能匹配一次。

  4) 跑最大流算法,如果最大流maxflow==n*mid,则表明当前轮数mid是合法的,否则不合法。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int MAXM = 1e5+;
const int MAXN = 2e2+; int uN, vN;
int maze[MAXN][MAXN];
int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];
int flow[MAXN][MAXN]; int sap(int start, int end, int nodenum)
{
memset(cur, , sizeof(cur));
memset(dis, , sizeof(dis));
memset(gap, , sizeof(gap));
memset(flow, , sizeof(flow));
int u = pre[start] = start, maxflow = , aug = INF;
gap[] = nodenum; while(dis[start]<nodenum)
{
loop:
for(int v = cur[u]; v<nodenum; v++)
if(maze[u][v]-flow[u][v]> && dis[u] == dis[v]+)
{
aug = min(aug, maze[u][v]-flow[u][v]);
pre[v] = u;
u = cur[u] = v;
if(v==end)
{
maxflow += aug;
for(u = pre[u]; v!=start; v = u, u = pre[u])
{
flow[u][v] += aug;
flow[v][u] -= aug;
}
aug = INF;
}
goto loop;
} int mindis = nodenum-;
for(int v = ; v<nodenum; v++)
if(maze[u][v]-flow[u][v]> && mindis>dis[v])
{
cur[u] = v;
mindis = dis[v];
}
if((--gap[dis[u]])==) break;
gap[dis[u]=mindis+]++;
u = pre[u];
}
return maxflow;
} bool test(int mid)
{
int start = , end = uN+vN+;
for(int i = ; i<=uN; i++) maze[start][i] = mid;
for(int i = ; i<=vN; i++) maze[uN+i][end] = mid;
return sap(start, end, uN+vN+)==uN*mid;
} void flyod(int N)
{
for(int k = ; k<=N; k++)
for(int i = ; i<=N; i++)
for(int j = ; j<=N; j++)
maze[i][j] = maze[i][j]||(maze[i][k]&&maze[k][j]);
} int main()
{
int T, n, m, f;
scanf("%d", &T);
while(T--)
{
scanf("%d%d%d", &n,&m,&f);
uN = vN = n;
memset(maze, , sizeof(maze));
for(int i = ; i<=m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
maze[u][uN+v] = ;
}
for(int i = ; i<=f; i++)
{
int u, v;
scanf("%d%d", &u, &v);
maze[u][v] = maze[v][u] = ;
} flyod(uN+vN);
int l = , r = uN;
while(l<=r)
{
int mid = (l+r)/;
if(test(mid))
l = mid + ;
else
r = mid - ;
}
printf("%d\n", r);
}
}

HDU3081 Marriage Match II —— 传递闭包 + 二分图最大匹配 or 传递闭包 + 二分 + 最大流的更多相关文章

  1. HDU 3081 Marriage Match II (二分图,并查集)

    HDU 3081 Marriage Match II (二分图,并查集) Description Presumably, you all have known the question of stab ...

  2. HDU3081:Marriage Match II (Floyd/并查集+二分图匹配/最大流(+二分))

    Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  3. hdu3081 Marriage Match II(最大流)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Marriage Match II Time Limit: 2000/1000 M ...

  4. hdu3081 Marriage Match II(二分+并查集+最大流)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意: n个女生与n个男生配对,每个女生只能配对某些男生,有些女生相互是朋友,每个女生也可以跟她 ...

  5. HDU 3081:Marriage Match II(二分图匹配+并查集)

    http://acm.hdu.edu.cn/showproblem.php?pid=3081 题意:有n个男生n个女生,他们只有没有争吵或者女生a与男生A没有争吵,且女生b与女生a是朋友,因此女生b也 ...

  6. hdu3081 Marriage Match II

    新年第一篇,又花了一早上,真是蠢啊! 二分+网络流 之前对于讨论哪些人是朋友的时候复杂度过高 直接n3的暴力虽然看起来复杂度高,其实并不是每次都成立 #include<bits/stdc++.h ...

  7. HDU 3081 Marriage Match II (网络流,最大流,二分,并查集)

    HDU 3081 Marriage Match II (网络流,最大流,二分,并查集) Description Presumably, you all have known the question ...

  8. HDU 3081 Marriage Match II(二分法+最大流量)

    HDU 3081 Marriage Match II pid=3081" target="_blank" style="">题目链接 题意:n个 ...

  9. Marriage Match II(二分+并查集+最大流,好题)

    Marriage Match II http://acm.hdu.edu.cn/showproblem.php?pid=3081 Time Limit: 2000/1000 MS (Java/Othe ...

随机推荐

  1. POSTMAN编写文档

    第一步:创建文件夹: 同时创建全局变量: 第二步:创建分组文件夹: 第三步:添加请求: 类似正常调试,然后多了一步保存: 保存: 请求方式发生相应变化,同时颜色也发生变化,说明保存成功: ====== ...

  2. 转载免费的SSL证书

    目前我知道的有2种方式进行免费的SSL证书的获取 第一种:腾讯云申请 第二种:Let's Encrypt (国外在) 我一直使用第一种,还可以,有效期1年. 以下转载第二种: 实战申请Let's En ...

  3. codeforces Gym 101572 I 有向图最小环路径

    题目链接 http://codeforces.com/gym/101572 题意  一共n个文件  存在依赖关系 根据给出的依赖关系   判断是否存在循环依赖 ,不存在的话输出SHIP IT,存在的话 ...

  4. Codeforces 849B Tell Your World (计算几何)

    题目链接 Tell Your World 题意 给出N个点(i, xi),问是否存在两条平行的直线,使得每一个点恰好在两条直线的其中一条上. 每条直线必须穿过至少一个点. 考虑每个点和第1个点的斜率, ...

  5. Java中Class.this和this的区别(转)

    当inner class(内部类)必顺使用到outer class(外部类)的this instance(实例)时,或者匿名内部类要使用外部类的实例. 例: class Outer{ String d ...

  6. Jenkins使用Publish Over FTP Plugin插件上传FTP详解

    一.安装插件[Publish Over FTP] 二.在[系统管理]->[系统设置]->[Publish over FTP]->点击[增加]按钮,增加一个要连接的FTP: FTP S ...

  7. Android:BLE智能硬件开发详解

    目录 前言 BLE是个什么鬼 BLE中的角色分工 主要的关键词和概念 GATT(Generic Attribute Profile ) Characteristic Service Android如何 ...

  8. 标准IO函数以及基本知识点总结

    什么是标准IO呢?有哪些特点? 标准IO是标准c库提供的对文件操作的函数接口.他的特点是:1 带缓存,2 大部分都调用系统接口函数实现.(c库就是一种实现好的函数接口,作用是屏蔽下层细节.提供上层接口 ...

  9. CentOS 6.x安装多GCC版本号,cmake的安装与使用

    操作系统:CentOS release 6.5 (Final) 当前gcc版本号:build=x86_64-redhat-linux                           Thread ...

  10. BUPT复试专题—图像压缩存储(2015)

    题目描述 以二维数组表示图像,其值只有0.1两种,寻找两幅图像中最大的相同方阵   输入 第一行输入一个n,接下来的2n行输入两个n*n数组,寻找一个最大的m*m子区域,使得两个数组在该子区域完全相同 ...