洛谷P1330 封锁阳光大学 [图论,染色]

  题目传送门

封锁阳光大学

题目描述

曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街。河蟹看到欢快的曹,感到不爽。河蟹决定封锁阳光大学,不让曹刷街。

阳光大学的校园是一张由N个点构成的无向图,N个点之间由M条道路连接。每只河蟹可以对一个点进行封锁,当某个点被封锁后,与这个点相连的道路就被封锁了,曹就无法在与这些道路上刷街了。非常悲剧的一点是,河蟹是一种不和谐的生物,当两只河蟹封锁了相邻的两个点时,他们会发生冲突。

询问:最少需要多少只河蟹,可以封锁所有道路并且不发生冲突。

输入输出格式

输入格式:

 

第一行:两个整数N,M

接下来M行:每行两个整数A,B,表示点A到点B之间有道路相连。

 

输出格式:

 

仅一行:如果河蟹无法封锁所有道路,则输出“Impossible”,否则输出一个整数,表示最少需要多少只河蟹。

 

输入输出样例

输入样例#1: 复制
3 3
1 2
1 3
2 3
输出样例#1: 复制
Impossible
输入样例#2: 复制
3 2
1 2
2 3
输出样例#2: 复制
1

说明

【数据规模】

1<=N<=10000,1<=M<=100000,任意两点之间最多有一条道路。


  分析:

  思路非常巧妙的一道图论题,也是理解染色问题的一道好题。

  首先,题目并没有保证是一个连通图,但经过分析也可以知道,只要每个子连通图都满足要求即可。重点在于,题目要求每一条边的连个端点必须有且仅有一个端点被占。那么实际上也就等效于,任意两个相邻的点必须被染成不同的颜色。那么思路有了就好做了,直接深搜或者广搜都行,遍历每个子连通图判断是否可以按照该原则染色即可。具体看代码。

  Code:

 1 //It is made by HolseLee on 9th June 2018
 2 //Luogu.org P1330
 3 #include<bits/stdc++.h>
 4 using namespace std;
 5 const int N=1e4+7;
 6 const int M=1e5+7;
 7 bool vis[N];
 8 int n,m,head[N],size,col[N],sum[2],ans;
 9 struct Node{int to,next;}edge[M<<1];
10 inline int read()
11 {
12     char ch=getchar();int num=0;bool flag=false;
13     while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
14     while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
15     return flag?-num:num;
16 }
17 inline void add(int x,int y)
18 {
19     edge[++size].to=y;
20     edge[size].next=head[x];
21     head[x]=size; 
22 }
23 inline bool dfs(int u,int color)
24 {
25     if(vis[u]){
26         if(col[u]==color)return true;
27         return false;}
28     vis[u]=true;sum[col[u]=color]++;
29     bool flag=true;
30     for(int i=head[u];i!=-1;i=edge[i].next){
31         flag=flag&&dfs(edge[i].to,1-color);}
32     return flag;
33 }
34 int main()
35 {
36     memset(head,-1,sizeof(head));
37     memset(vis,false,sizeof(vis));
38     n=read();m=read();int x,y;
39     for(int i=1;i<=m;i++){
40         x=read();y=read();
41         add(x,y);add(y,x);}
42     for(int i=1;i<=n;i++){
43         if(vis[i])continue;
44         sum[0]=sum[1]=0;
45         if(!dfs(i,0)){
46             printf("Impossible");
47             return 0;}
48         ans+=min(sum[0],sum[1]);}
49     printf("%d",ans);
50     return 0;
51 }

猜你喜欢

转载自www.cnblogs.com/cytus/p/9159200.html
今日推荐