题意:有n个学生,有m对人是认识的,每一对认识的人能分到一间房,问能否把n个学生分成两部分,每部分内的学生互不认识,而两部分之间的学生认识。如果可以分成两部分,就算出房间最多需要多少间,否则就输出No
判断二分图后是的话求一下最大匹配
链接:hdu - 2444
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1000;
const int maxm = 1000;
int used[maxn];
int link[maxn];
int mat[maxn][maxn];
int gn, gm;
int color[maxn];
int dfs(int t) {
for(int i = 1; i <= gm; i++) {
if(!used[i] && mat[t][i]) {
used[i] = 1;
if(link[i] == -1 || dfs(link[i])) {
link[i] = t;
return 1;
}
}
}
return 0;
}
int maxmatch() {
int num = 0;
memset(link, 0xff, sizeof(link));
for(int i = 1; i <= gn; i++) {
memset(used, 0, sizeof(used));
if(dfs(i)) {
num++;
}
}
return num;
}
bool judge(int x) {
for(int i = 1; i <= gn; i++) {
if(i != x && mat[x][i]) {
if(color[i] == -1) {
color[i] = (color[x] + 1) % 2;
if(!judge(i))
return 0;
}
else if(color[i] == color[x])
return 0;
}
}
return 1;
}
int main()
{
int n, m, k, t;
while(~scanf("%d %d", &n, &m)) {
gn = gm = n;
memset(mat, 0, sizeof(mat));
memset(color, -1, sizeof(color));
while(m--) {
int a, b;
scanf("%d %d", &a, &b);
mat[a][b] = mat[b][a] = 1;
}
int flag = judge(1);
if(flag) {
int res = maxmatch();
printf("%d\n", res / 2);
}
else {
puts("No");
}
}
return 0;
}