洛谷1330:曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街。河蟹看到欢快的曹,感到不爽。河蟹决定封锁阳光大学,不让曹刷街。
阳光大学的校园是一张由N个点构成的无向图,N个点之间由M条道路连接。每只河蟹可以对一个点进行封锁,当某个点被封锁后,与这个点相连的道路就被封锁了,曹就无法在与这些道路上刷街了。非常悲剧的一点是,河蟹是一种不和谐的生物,当两只河蟹封锁了相邻的两个点时,他们会发生冲突。
询问:最少需要多少只河蟹,可以封锁所有道路并且不发生冲突。
显然这是一道可以算是比较经典的染色问题了(二分图判断)。我们进行黑白着色,如果当前的点已经有了颜色,并且颜色和要给它染得不相同,那么说明相邻的两点有两只螃蟹了,不符合题意,否则继续。然后统计出黑色和白色的个数,去最小的即可(注明:二分图一般都是无向图)
代码如下:
- #include<iostream>
- #include<cstring>
- #include<string>
- #include<algorithm>
- #include<cmath>
- #include<cstdio>
- using namespace std;
- int n,m,x,y,ans1,ans2;
- int head[100005],colour[100005];
- struct Edge{
- int next,to;
- }e[100005];
- int k=0;
- void add(int x,int y)
- {
- k++;
- e[k].next=head[x];
- e[k].to=y;
- head[x]=k;
- }
- void dfs(int u,int tot)
- {
- if (colour[u]!=0&&colour[u]!=tot){
- cout<<"Impossible"<<endl;
- exit(0);
- }
- if (colour[u]) return;
- if (tot==1) ans1++;
- else ans2++;
- colour[u]=tot;
- for (int i=head[u];i;i=e[i].next){
- int v=e[i].to;
- dfs(v,3-tot);
- }
- }
- int main()
- {
- scanf("%d%d",&n,&m);
- for (int i=1;i<=m;i++){
- scanf("%d%d",&x,&y);
- add(x,y);
- add(y,x);
- }
- int ans=0;
- memset(colour,0,sizeof(colour));
- for (int i=1;i<=n;i++){
- if (!colour[i]){
- ans1=ans2=0;
- dfs(i,1);
- ans=ans+min(ans1,ans2);
- }
- }
- if (ans==0) printf("Impossible\n");
- else printf("%d\n",ans);
- return 0;
- }