题目:
1 4 5 2 1 1 2 3 3 2 4 2 4 4 1 4 2 3
2
就是给你n个男孩和n个女孩,进行两两(男女)配对玩过家家的游戏。配对的条件是女的和男的是朋友关系或者女A和女B是朋友关系,女A跟男A是朋友关系,女B和男A也可以进行配对。玩过一轮过家家游戏之后,则这两个人不能再一起配对。求最多玩几轮过家家游戏。
思路:
刚开始做这道题的时候,解决不了女女之间是朋友关系的情况该怎么处理,后来看了下别人的思路要用并查集,所以这才做出来。每次配对完之后看下能不能达到n对,如果能的话就次数加1,并且删除已经配对的边,再进行下一次的配对,直到进行配对的人数小于n时,跳出配对。
代码以及解释如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define PI 2*asin(1.0)
const int MOD = 1e9 + 7;
const int N = 1e2 + 15;
const int INF = (1 << 30) - 1;
using namespace std;
int n, m, f;
int a, b;
int g[N][N];
int father[N];
///利用并查集进行合并
int Find(int x) {
if(x == father[x]) return x;
return x = Find(father[x]);
}
void Union(int a, int b) {
int aa = Find(a);
int bb = Find(b);
if(aa != bb) father[bb] = aa;
}
void init() {
for(int i = 1; i <= n; i++) father[i] = i;
memset(g, 0, sizeof(g));
}
///匈牙利算法进行二分匹配
int cx[N], cy[N]; ///匹配
int sx[N], sy[N];
int path(int u) {
sx[u] = 1;
for(int i = 1; i <= n; i++) {
if(g[u][i] && !sy[i]) {
sy[i] = 1;
///如果i没有匹配,或者i匹配了,但从cy[i]能找到增广路
if(cy[i] == -1 || path(cy[i])) { ///查找
cx[u] = i, cy[i] = u;
return 1;///找到增广路
}
}
}
return 0;
}
///删除已经匹配的边
void Del() {
for(int i = 1; i <= n; i++)
g[i][cx[i]] = 0;
}
int maxflow() {
int ans = 0;
while(1) {
memset(cx, -1, sizeof(cx));
memset(cy, -1, sizeof(cy));
int flow = 0;
for(int i = 1; i <= n; i++) {
memset(sx, 0, sizeof(sx));
memset(sy, 0, sizeof(sy));
if(cx[i] == -1) flow += path(i);///没有匹配的进行匹配
}
///是否达到条件
if(flow == n) {
ans++;
Del();
} else break;
}
return ans;
}
int main() {
int tc;
scanf("%d", &tc);
while(tc--) {
scanf("%d%d%d", &n, &m, &f);
init();
for(int i = 0; i < m; i++) {
scanf("%d%d", &a, &b);
g[a][b] = 1;
}
///朋友关系进行合并,为了之后更好的查找
for(int i = 0; i < f; i++) {
scanf("%d%d", &a, &b);
Union(a, b);
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++) {
if(i == j) continue;
if(Find(i) == Find(j)) {///朋友关系的话,朋友之间可以共享
for(int k = 1; k <= n; k++) {
if(g[i][k]) g[j][k] = 1;
}
}
}
printf("%d\n", maxflow());
}
return 0;
}
原文地址:http://blog.csdn.net/u014325920/article/details/40582335