有n個關係,他們之間某些人相互認識。這樣的人有m對。
你需要把人分成2組,使得每組人內部之間是相互不認識的。
如果可以,就可以安排他們住宿了。安排住宿時,住在一個房間的兩個人應該相互認識。
最多的能有多少個房間住宿的兩個相互認識。
首先題目是要問能不能分成兩組,每組人之間互相不認識,每個人只與對面那部分的人認識。這個就是要判斷是不是能構成一個二分圖的樣子。
判斷二分圖我們使用染色法,就是規定一個點的顏色,然後與其相連的點的顏色是不同的,如果遇到了無法滿足的情況,(比如之前顏色是1 , 但是到現在你又要這個點顏色是2就無法滿足)。判斷是二分圖後,直接二分圖匹配模板就可以了。還有個小問題就是,我們二分圖匹配出來的數目要除以2,因爲他是比如1和2匹配,2和1匹配算作了兩種,所以答案去除以2就好了。
有任何問題儘管留言,我會盡量回復。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<time.h>
#include<cmath>
using namespace std;
const long long max_ = 1e3 + 7;
int tu[max_][max_];
int read()
{
int s = 0, f = 1;
char ch = getchar();
while (ch<'0' || ch>'9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0'&&ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * f;
}
int n, m, e, vis[max_], match[max_];
int dfs(int now) {
for (int i = 1; i <= n; i++) {
if (tu[now][i] && !vis[i]) {
vis[i] = 1;
if (match[i] == 0 || dfs(match[i])) {
match[i] = now;
return 1;
}
}
}
return 0;
}
int color[max_];
int bfs(int now) {
queue<int>node;
node.push(now);
while (!node.empty()) {
int tou = node.front();
node.pop();
for (int i = 1; i <= n; i++) {
if (tu[tou][i] == 1) {
if (color[i] == 0) {
color[i] = (color[tou] == 1 ? 2 : 1);
node.push(i);
}
else {
if (color[i] == color[tou])return 0;
}
}
}
}
return 1;
}
void qing() {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
tu[i][j] = 0;
}
match[i] = 0;
color[i] = 0;
}
}
int main() {
while (scanf_s("%d%d", &n,&m)!=EOF) {
qing();
while (m--) {
int a = read(), b = read();
tu[a][b] = 1;
tu[b][a] = 1;
}
int sum = 0;
color[1] = 1;
if (!bfs(1)||n==1) { cout << "No" << endl; continue; }
for (int i = 1; i <= n; i++) {
memset(vis, 0, sizeof(vis));
sum += dfs(i);
}
cout << sum/2 << endl;
}
return 0;
}