HDU 3081--【二分图 && 传递闭包 && 完美匹配次数 && 经典】

Marriage Match II

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2794    Accepted Submission(s): 938

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

题意:

有 2*n个同学,n男n女,有 m 对男女之间木有吵过架(有关系),f  对女生互为朋友(有关系),现在这 n 个女生要找对象,要求没有和她吵过架或者没有和她朋友吵过架,

当 n 个女生都找到对象的时候算作一轮,然后重新找,满足每个女生都不能找和上次一样的对象,问最多能进行多少轮。(可以理解为经过多少轮游戏不存在完美匹配)。

解析:

首先把女生之间的关系传递闭包一下。有关系的男女之间建边,构造二分图。每次用匈牙利算法求一下最大匹配。若是完美匹配,删去当前的边,接着求最大匹配,直到不是完美匹配为止。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 110
using namespace std;
int map[maxn][maxn];//男女关系
int node[maxn][maxn];//女生之间的朋友关系
int used[maxn];
int link[maxn];
int n, m, f;

void init(){
    memset(map, 0, sizeof(map));
    memset(node, 0, sizeof(node));
}

void floyd(){
    for(int k = 1; k <= n; ++k)
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                node[i][j] = node[i][j] || (node[i][k] && node[k][j]);
}

void getmap(){
    scanf("%d%d%d", &n, &m, &f);
    int a, b;
    while(m--){
        scanf("%d%d", &a, &b);
        map[a][b] = 1;
    }
    while(f--){
        scanf("%d%d", &a, &b);
        node[a][b] = node[b][a] = 1;
    }
    floyd();
    for(int i = 1; i <= n; ++i){//枚举每一个女生
        for(int j = 1; j <= n; ++j){
            if(node[i][j]){//女生i , j之间为朋友关系
                for(int k = 1; k <= n; ++k){
                    //若女生i 和男生 k 可以做伴侣,
                    //则女生j 和男生 k 也可以做伴侣
                    if(map[i][k])
                        map[j][k] = 1;
                }
            }
        }
    }
}

bool dfs(int x){
    for(int i = 1; i <= n; ++i){
        if(map[x][i] && !used[i]){
            used[i] = 1;
            if(link[i] == -1 || dfs(link[i])){
                link[i] = x;
                return true;
            }
        }
    }
    return false;
}

int hungary(){
    int ans = 0;
    memset(link, -1, sizeof(link));
    for(int i = 1; i <= n; ++i){
        memset(used, 0, sizeof(used));
        if(dfs(i))
            ans++;
    }
    return ans;
}

void solve(){
    int num = 0;
    while(1){
        int sum = hungary();
        if(sum == n){
            num++;
            for(int i = 1; i <= n; ++i)
                map[link[i]][i] = 0;
        }
        else
            break;
    }
    printf("%d\n", num);
}

int main (){
    int T;
    scanf("%d", &T);
    while(T--){
        init();
        getmap();
        solve();
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 22:32:54

HDU 3081--【二分图 && 传递闭包 && 完美匹配次数 && 经典】的相关文章

HDU_2255 二分图最佳完美匹配 KM匈牙利算法

一开始还没看懂这个算法,后来看了陶叔去年的PPT的实例演示才弄懂 用一个lx[]和ly[]来记录X和Y集合中点的权值,有个定理是 lx[i]+ly[j]==w[i][j](边权值) 则该点是最佳匹配,因为首先 那个不等式肯定要>=的,否则就不满足题意了,如果是>则可以去匹配更有价值的边或者把权值降下来让匹配边的潜力更大. 所以只有把握了这个条件,其他就是走一遍最大匹配数.以及up()函数用来在无法匹配的时候,进行其他点的权值降低(也可以说是增广路的搜索)来得到匹配. #include <

codevs 1222 信与信封问题(二分图的完美匹配)

1222 信与信封问题 题目描述 Description John先生晚上写了n封信,并相应地写了n个信封将信装好,准备寄出.但是,第二天John的儿子Small John将这n封信都拿出了信封.不幸的是,Small John无法将拿出的信正确地装回信封中了. 将Small John所提供的n封信依次编号为1,2,…,n:且n个信封也依次编号为1,2,…,n.假定Small John能提供一组信息:第i封信肯定不是装在信封j中.请编程帮助Small John,尽可能多地将信正确地装回信封. 输入

UVa 11383 少林决胜(二分图最佳完美匹配)

https://vjudge.net/problem/UVA-11383 题意: 给定一个N×N矩阵,每个格子里都有一个正整数W(i,j).你的任务是给每行确定一个整数row(i),每列也确定一个整数col(i),使得对于任意格子(i,j),w(i,j)<=row(i)+col(j).所有的row(i)和col(i)只和应尽量小. 思路: 利用二分图最佳完美匹配当中的l(x)+l(y)>=w(i,j),直接用KM算法即可. 1 #include<iostream> 2 #inclu

UVA - 1045 The Great Wall Game(二分图最佳完美匹配)

题目大意:给出棋盘上的N个点的位置.如今问将这些点排成一行或者一列.或者对角线的最小移动步数(每一个点都仅仅能上下左右移动.一次移动一个) 解题思路:暴力+二分图最佳完美匹配 #include <cstdio> #include <cstring> #define N 20 #define INF 0x3f3f3f3f #define abs(x) ((x) > 0 ? (x) : (-(x))) #define max(a,b)((a)>(b)? (a):(b)) #

HDU 3722 Card Game(二分图最佳完美匹配+KM算法)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3722 1 /* 2 问题 3 将任意的两个字符串进行匹配,使得匹配后权值和最大 4 5 解题思路 6 将任意的字符串的权值计算出来,使用KM算法即可. 7 */ 8 #include<cstdio> 9 #include<cstring> 10 #include<algorithm> 11 using namespace std; 12 13 const int maxn

hdu 2255 二分图最大权匹配 *

题意:说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子.另 一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格, 比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出2

HDU 1533 二分图最小权匹配 Going Home

带权二分图匹配,把距离当做权值,因为是最小匹配,所以把距离的相反数当做权值求最大匹配. 最后再把答案取一下反即可. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <map> 6 #include <vector> 7 #include <cmath> 8 #define MP

Marriage Match II (hdu 3081 二分图+并查集)

Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2455    Accepted Submission(s): 837 Problem Description Presumably, you all have known the question of stable marriage match. A

UVALive 4043 Ants 蚂蚁(二分图最佳完美匹配)

题意:n个蚂蚁n棵树,蚂蚁与树要配对,在配对成功的一对之间连一条线段,要求所有线段不能相交.按顺序输出蚂蚁所匹配的树. 思路:这个题目真是技巧啊,如果知道要求的就是整体最优,那么就容易做了.而不能用贪心来为每个蚂蚁选择最近的树,这样可能八成还是相交了. 整体最优能让每条线段不相交,证明: 假设a1-b1与a2-b2相交.则dis(a1,b1)+dis(a2,b2)>=dis(a1,b2)+dis(a2,b1).如果我们所决定的最优匹配是按照整体距离最短来匹配的,那么dis(a1,b1)+dis(