洛谷P1330 封鎖陽光大學

題面

陽光大學的校園是一張由 n 個點構成的無向圖,n 個點之間由 m 條道路連接。每隻河蟹可以對一個點進行封鎖,當某個點被封鎖後,與這個點相連的道路就被封鎖了。非常悲劇的一點是,河蟹是一種不和諧的生物,當兩隻河蟹封鎖了相鄰的兩個點時,他們會發生衝突。

詢問:最少需要多少隻河蟹,可以封鎖所有道路並且不發生衝突。

分析

這個模型抽象一下,即是1.沒有相鄰的河蟹2.要封鎖全部道路,不難想到二分圖,如果這個圖能夠二分(頂點劃分兩個子集,只存在子集間的邊而不存在子集內的邊),那麼就可以將一部分的頂點全放河蟹,另一部分都空着,達成目標(也可以理解爲兩種染色)

在bfs/dfs中染色並檢查即可

代碼

#include "cstdlib"
#include <iostream>
#include <stdio.h>
#include <string.h>
#include<algorithm>
#include <string>
#include<vector>
#include<queue>
using namespace std;
vector<int> edge[100005];
int col[10005];//0表示未染色,1,2表示不同的染色,相同的染色不能相鄰
int R = 0, B = 0;
queue<int>q;
int bfs(int start)
{
	int flag = 1,size,t;
	q.push(start);
	col[start] = 1,R++;
	while (!q.empty())
	{
		t = q.front();
		q.pop();
		size = edge[t].size();
		for (int i = 0; i < size; i++)
		{
			if(col[edge[t][i]]==0)//遇到未染色的點,染色並加入
			{
				q.push(edge[t][i]);
				if (col[t] == 1)col[edge[t][i]] = 2,B++;
				else col[edge[t][i]] = 1,R++;
			}
			else {//遇到已經染色的,進行檢查
				if (col[t] == 1 && col[edge[t][i]] == 1) { flag = 0; break; }
				if (col[t] == 2 && col[edge[t][i]] == 2) { flag = 0; break; }
			}
		}
		if (!flag)break;
	}
	return flag;
}
int main()
{
	ios::sync_with_stdio(false);
	int n, m,u,v;
	cin >> n >> m;
	for (int i = 0; i < m; i++)
	{
		cin >> u >> v;
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	int ans = 0;
	for (int i = 1; i <= n; i++)
	{
		if (col[i])continue;//有不連通的塊,所以一次遍歷不能解決問題,但也不能重複遍歷
		R = 0, B = 0;//初始兩種染色的數量都爲0
		if (!bfs(i)) {//不可染色
			cout << "Impossible";
			return 0;
		}
		ans += min(R, B);
	}
	cout << ans;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章