题目大意:
有n个学生,有m对人是认识的,每一对认识的人能分到一间房,问能否把n个学生分成两部分,每部分内的学生互不认识,而两部分之间的学生认识。如果可以分成两部分,就算出房间最多需要多少间,否则就输出No。
解题思路:
先是要判断是否为二部图,然后求最大匹配。
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <stack> #include <algorithm> using namespace std; const int MAXN = 200 +10; struct Edge { int to; int next; }edge[MAXN*MAXN]; int n, m; int e; int head[MAXN]; int vis[MAXN]; int col[MAXN]; int match[MAXN]; void AddEdge(int u, int v) { edge[e].to = v; edge[e].next = head[u]; head[u] = e; e++; edge[e].to = u; edge[e].next = head[v]; head[v] = e; e++; } bool dfs(int u, int pre) { for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].to; if(v == pre) continue; if(col[v] == -1) { col[v] = col[u] ^ 1; dfs(v, u); } else if(col[v] == col[u]) return false; } return true; } int path(int u) { for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].to; if(vis[v]) continue; vis[v] = 1; if(match[v] == -1 || path(match[v])) { match[v] = u; return 1; } } return 0; } int main() { while(scanf("%d%d", &n, &m)!=EOF) { memset(head, -1, sizeof(head)); memset(match, -1, sizeof(match)); memset(vis, 0, sizeof(vis)); memset(col, -1, sizeof(col)); e = 0; int u, v; for(int i=1;i<=m;i++) { scanf("%d%d", &u, &v); AddEdge(u, v); } int ans = 0; col[1] = 1; if(!dfs(1, -1)) { printf("No\n"); continue; } else { for(int i=1;i<=n;i++) { memset(vis, 0, sizeof(vis)); if(path(i)) ans++; } printf("%d\n", ans / 2); } } return 0; }
时间: 2024-10-22 16:56:23