題面
陽光大學的校園是一張由 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;
}