题目:
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; }