题目大意:有一群人他们有一些关系,比如A认识B, B认识C, 但是这并不意味值A和C认识。现在给你所有互相认识的学生,你的任务是把所有的学生分成两个一组,
住在一个双人房里。相互认识的同学可以住在一个双人房里。
输入数据:
有n个学生 m个关系(m对是相互认识的)
接下来m行是,是m个关系。
如果能够匹配成功则输出需要双人房的个数,否则输出‘No‘
思路:先判断是否是个二分图,可以使用黑白染色的方法来判断。然后再进行最大匹配。
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; #define maxn 500 bool G[maxn][maxn], vis[maxn]; int color[maxn], P[maxn];///黑白染色 -1 黑色 1 白色 int n, m; bool DFS(int u,int c)///判断是否是二分图,黑白染色 { color[u] = c; for(int i=1; i<=n; i++) { if(!G[u][i] ) continue; if(color[i] == 0) { if( DFS(i, -c) ) continue; return false; } else if(color[i] + color[u]) return false; } return true; } bool Find(int u) { for(int i=1; i<=n; i++) { if(G[u][i] && !vis[i]) { vis[i] = true; if(P[i] == -1 || Find(P[i])) { P[i] = u; return true; } } } return false; } int solve() { bool ok; for(int i=1; i<=n; i++) { if(color[i] == 0) ok = DFS(i, 1); if(ok == false) return -1; } int ans = 0; for(int i=1; i<=n; i++) { memset(vis, false, sizeof(vis)); if(color[i] && Find(i)) ans ++; } return ans; } int main() { while(scanf("%d %d",&n, &m) != EOF) { int a, b; memset(G, false, sizeof(G)); memset(P, -1, sizeof(P)); memset(color, 0, sizeof(color)); for(int i=0; i<m; i++) { scanf("%d %d",&a, &b); G[a][b] = true; } int ans = solve(); if(ans == -1) puts("No"); else printf("%d\n", ans ); } return 0; }
时间: 2025-01-19 00:40:49