题目来源:
题目描述:
题目描述
曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街。河蟹看到欢快的曹,感到不爽。河蟹决定封锁阳光大学,不让曹刷街。
阳光大学的校园是一张由N个点构成的无向图,N个点之间由M条道路连接。每只河蟹可以对一个点进行封锁,当某个点被封锁后,与这个点相连的道路就被封锁了,曹就无法在与这些道路上刷街了。非常悲剧的一点是,河蟹是一种不和谐的生物,当两只河蟹封锁了相邻的两个点时,他们会发生冲突。
询问:最少需要多少只河蟹,可以封锁所有道路并且不发生冲突。
输入输出格式
输入格式:第一行:两个整数N,M
接下来M行:每行两个整数A,B,表示点A到点B之间有道路相连。
输出格式:仅一行:如果河蟹无法封锁所有道路,则输出“Impossible”,否则输出一个整数,表示最少需要多少只河蟹。
输入输出样例
说明
【数据规模】
1<=N<=10000,1<=M<=100000,任意两点之间最多有一条道路。
解题思路:
1.首先图可能不连通,所以要图分成一个个连通的图来做,在每一个连通图中,因为相邻的点不能同时封锁,所以我们考虑用两种颜色染色,相邻的不能染同一种颜色,那样再取两种颜色数较小的那个,这个数就是这一个连通图需要的河蟹数,最后再把所有连通图的结果加起来就行。
2.用dfs来判断连通图的数量,并且可以标记,在染色的时候使用bfs来进行,ans+=min(sum1,sum2)就行,最后输出ans
代码:
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
int ls[10005],lt[10005],gs;
struct newt{
int num,ys;
}dian;
vector<int>E[10005];
void dfs(int u)
{
lt[u]=gs;
for(int i=0;i<E[u].size();i++)
{
int v=E[u][i];
if(!lt[v]){
dfs(v);
}
}
}
int main()
{
int n,m;
cin>>n>>m;
memset(ls,0,sizeof(ls));
memset(lt,0,sizeof(lt));
for(int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
E[a].push_back(b);
E[b].push_back(a);
}
gs=0;
for(int i=1;i<=n;i++)
{
if(!lt[i]){
gs++;
dfs(i);
}
}
int flag=0,ans=0;
for(int i=1;i<=gs;i++)
{
int sum1=0,sum2=0;
if(flag){
break;
}
queue<newt>q;
for(int j=1;j<=n;j++)
{
if(lt[j]==i){
dian.num=j;dian.ys=1;
q.push(dian);
break;
}
}
while(!q.empty())
{
if(flag)break;
newt now=q.front();
ls[now.num]=now.ys;
if(now.ys==1)sum1++;
else sum2++;
q.pop();
for(int j=0;j<E[now.num].size();j++)
{
int v=E[now.num][j];
if(!ls[v]){
newt nod;
nod.num=v;
if(now.ys==1){
nod.ys=2;
q.push(nod);
ls[v]=2;
}
else{
nod.ys=1;
q.push(nod);
ls[v]=1;
}
}
else{
if(ls[v]==now.ys){
flag=1;break;
}
}
}
}
ans+=min(sum1,sum2);
}
// for(int i=1;i<=n;i++)
// cout<<ls[i]<<" ";
if(!flag)
cout<<ans<<endl;
else cout<<"Impossible"<<endl;
return 0;
}