[POI2010]GIL-Guilds(结论题)
题意
给一张无向图,要求你用黑白灰给点染色,且满足对于任意一个黑点,至少有一个白点和他相邻;对于任意一个白点,至少有一个黑点与他相邻,对于任意一个灰点,至少同时有一个黑点和白点和灰点与他相邻,问能否成功n(<=200000) and m(<=500000)
题解
我一开始以为是一定成功。
结果忘了一个独立点的情况。
我们知道树一定是二分图。
所以用并查集求出每个联通块的随便一个生成树,跑bfs黑白染色即可。(甚至用不到灰色)
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 using namespace std; 8 const int N=200010; 9 const int M=500010; 10 int fa[N],n,m,cnt,book[N],col[N],head[N]; 11 struct edge{ 12 int to,nxt; 13 }e[M*3]; 14 void add(int u,int v){ 15 cnt++; 16 e[cnt].nxt=head[u]; 17 e[cnt].to=v; 18 head[u]=cnt; 19 } 20 int find(int x){ 21 if(fa[x]==x)return x; 22 else return fa[x]=find(fa[x]); 23 } 24 void bfs(int s,int c){ 25 queue<int> q; 26 q.push(s); 27 while(!q.empty()){ 28 int u=q.front(); 29 q.pop(); 30 for(int i=head[u];i;i=e[i].nxt){ 31 int v=e[i].to; 32 if(col[v]==-1){ 33 col[v]=col[u]^1; 34 q.push(v); 35 } 36 } 37 } 38 } 39 int main(){ 40 scanf("%d%d",&n,&m); 41 for(int i=1;i<=n;i++)fa[i]=i; 42 for(int i=1;i<=m;i++){ 43 int u,v; 44 scanf("%d%d",&u,&v); 45 int x=find(u); 46 int y=find(v); 47 if(x==y)continue; 48 book[u]=book[v]=1; 49 add(u,v); 50 add(v,u); 51 } 52 for(int i=1;i<=n;i++){ 53 if(book[i]==0){ 54 printf("NIE"); 55 return 0; 56 } 57 } 58 printf("TAK\n"); 59 memset(col,-1,sizeof(col)); 60 for(int i=1;i<=n;i++){ 61 if(col[i]==-1){ 62 col[i]=1; 63 bfs(i,1); 64 } 65 } 66 for(int i=1;i<=n;i++){ 67 if(col[i]==1)printf("K\n"); 68 else printf("S\n"); 69 } 70 return 0; 71 }