P1330 封锁阳光大学(染色问题)
Posted HWIM
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1330 封锁阳光大学(染色问题)相关的知识,希望对你有一定的参考价值。
题目描述
曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街。河蟹看到欢快的曹,感到不爽。河蟹决定封锁阳光大学,不让曹刷街。
阳光大学的校园是一张由N个点构成的无向图,N个点之间由M条道路连接。每只河蟹可以对一个点进行封锁,当某个点被封锁后,与这个点相连的道路就被封锁了,曹就无法在与这些道路上刷街了。非常悲剧的一点是,河蟹是一种不和谐的生物,当两只河蟹封锁了相邻的两个点时,他们会发生冲突。
询问:最少需要多少只河蟹,可以封锁所有道路并且不发生冲突。
输入输出格式
输入格式:
第一行:两个整数N,M
接下来M行:每行两个整数A,B,表示点A到点B之间有道路相连。
输出格式:
仅一行:如果河蟹无法封锁所有道路,则输出“Impossible”,否则输出一个整数,表示最少需要多少只河蟹。
输入输出样例
输入样例#1:
【输入样例1】 3 3 1 2 1 3 2 3 【输入样例2】 3 2 1 2 2 3
输出样例#1:
【输出样例1】 Impossible 【输出样例2】 1
说明
【数据规模】
1<=N<=10000,1<=M<=100000,任意两点之间最多有一条道路。
因为河蟹很不和谐,相邻的点是不能有河蟹的,也就是相邻的点的状态不能相同,这个问题就是染色问题:
对于一个点,可以它染成黑色或者白色,所以从第一个可染色的点开始染色,将它染成黑的或者是白的,之后搜索将整张图都染色,统计被染色的黑色总数和白色总数,在两者中取min即是最小放河蟹的数目。
注意:1、由于图不一定是联通的,搜索多次。2、M<=100000,开200000,双向建边,QAQ。
1 #include<cstdio> 2 #include<queue> 3 #include<cstdlib> 4 #include<algorithm> 5 using namespace std; 6 7 const int MAXN = 10100; 8 struct Edge{ 9 int to,nxt; 10 }e[200100]; //双向边乘2 11 int col[MAXN],head[MAXN]; 12 int n,m,cnt,ans; 13 queue<int>q; 14 15 void add(int u,int v) 16 { 17 ++cnt; 18 e[cnt].to = v; 19 e[cnt].nxt = head[u]; 20 head[u] = cnt; 21 } 22 23 int bfs(int a) 24 { 25 int ans1 = 0, ans2 = 0; 26 col[a] = 1; 27 ans1++; 28 q.push(a); 29 while (!q.empty()) 30 { 31 int u = q.front(); 32 q.pop(); 33 for (int i=head[u]; i; i=e[i].nxt) 34 { 35 int v = e[i].to; 36 if (col[v]==0) 37 { 38 if (col[u]==1) col[v] = 2, ans2++; 39 else if (col[u]==2) col[v] = 1, ans1++; 40 q.push(v); 41 } 42 else if (col[v]==col[u]) 43 { 44 printf("Impossible"); 45 exit(0); 46 } 47 } 48 } 49 return min(ans1,ans2); 50 } 51 52 int main() 53 { 54 scanf("%d%d",&n,&m); 55 for (int x,y,i=1; i<=m; ++i) 56 { 57 scanf("%d%d",&x,&y); 58 add(x,y); 59 add(y,x); 60 } 61 for (int i=1; i<=n; ++i) 62 if (!col[i]) ans += bfs(i); 63 printf("%d",ans); 64 return 0; 65 }
dfs代码简短一些,注意第29行。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 5 const int MAXN = 10100; 6 struct Edge{ 7 int to,nxt; 8 }e[200100]; //双向边乘2 9 int col[MAXN],head[MAXN]; 10 bool vis[MAXN],flag = true; 11 int n,m,cnt,ans,ans1,ans2; 12 13 void add(int u,int v) 14 { 15 ++cnt; 16 e[cnt].to = v; 17 e[cnt].nxt = head[u]; 18 head[u] = cnt; 19 } 20 21 void dfs(int u,int c) 22 { 23 vis[u] = true; 24 if (c==1) col[u]=2, ans2++; 25 else if (c==2) col[u] = 1, ans1++; 26 for (int i=head[u]; i; i=e[i].nxt) 27 { 28 int v = e[i].to; 29 if (vis[v]) //不能写成if(vis[i]&&col[u]==col[v]),影响到else的执行 30 { 31 if (col[v]==col[u]) 32 flag = false; 33 } 34 else dfs(v,col[u]); 35 } 36 } 37 int main() 38 { 39 scanf("%d%d",&n,&m); 40 for (int x,y,i=1; i<=m; ++i) 41 { 42 scanf("%d%d",&x,&y); 43 add(x,y); 44 add(y,x); 45 } 46 for (int i=1; i<=n; ++i) 47 if (!vis[i]) 48 { 49 ans1 = ans2 = 0; 50 dfs(i,1); 51 if (flag) ans += min(ans1,ans2); 52 else break; 53 } 54 if (flag) printf("%d",ans); 55 else printf("Impossible"); 56 return 0; 57 }
以上是关于P1330 封锁阳光大学(染色问题)的主要内容,如果未能解决你的问题,请参考以下文章