hdu2444 染色法+二分圖匹配

有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;
}
發佈了37 篇原創文章 · 獲贊 4 · 訪問量 4722
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章