洛谷 P3496 BZOJ 2079 [POI2010]GIL-Guilds
题目描述
King Byteasar faces a serious matter.
Two competing trade organisations, The Tailors Guild and The Sewers Guild asked, at the same time, for permissions to open their offices in each town of the kingdom.
There are towns in Byteotia.
Some of them are connected with bidirectional roads.
Each of the guilds postulate that every town should:
have an office of the guild, or be directly connected to another town that does.
The king, however, suspects foul play. He fears that if there is just a single town holding the offices of both guilds, it could lead to a clothing cartel.
For this reason he asks your help.
给一张无向图,要求你用黑白灰给点染色,且满足对于任意一个黑点,至少有一个白点和他相邻;对于任意一个白点,至少有一个黑点与他相邻,对于任意一个灰点,至少同时有一个黑点和白点和灰点与他相邻,问能否成功
输入格式
Two integers, n(<=200000) and m(<=500000), are given in the first line of the standard input. These denote the number of towns and roads in Byteotia, respectively.
The towns are numbered from 1 to n.
Then the roads are given as follows: the input line no. i+1 describes the i-th road;
输出格式
Your program should print out one word in the first line of the standard output:
TAK (yes in Polish) - if the offices can be placed in towns according to these rules, or NIE (no in Polish) - in the opposite case.
If the answers is TAK, then the following nlines should give an exemplary placement of the offices. Thus the line no. i+1 should hold:
the letter K if there should be an office of The Tailors Guild in the town i, or the letter S if there should be an office of The Sewers Guild in the town i, or the letter N if there should be no office in the town i.
输入输出样例
7 8 1 2 3 4 5 4 6 4 7 4 5 6 5 7 6 7
TAK K S K S K K N
说明/提示
题目spj贡献者@mengbierr
随想
昨天刚考完期末考。这学期真是日了狗了,几乎全程被拖着走,不总结、不预习、不复习,上课时间打瞌睡几乎没有听懂的东西,全是下来花更多时间自学,时间越来越不够用。感觉高数要挂科啊。算了,总结总结,反思一下,吸取教训,继续前进。(我多久没更博客了?多久没写代码了?可能我读的是个假计算机专业)。之后两周学术周听讲座,试着勾搭个教授,争取进实验室打杂吧;然后一周摸鱼(雾),制定一些长久一点的计划(一定要留有余地,机动性好一点),休息休息,调整作息,开始JB-ICPC集训。等到集训结束……然后就开学了啊
解题思路
百度了20分钟啥是 clothing cartel。
好吧,是找借口摸了20分钟鱼
题目没说灰色节点是不是必须的,那就不要灰色的了,灰色要求怪高的。然后BFS黑白染色(听说DFS会爆栈),搜索过程中遇到已经染过色的点,就跳过不管。对于每个连通块,看看染了多少个点,要是这个连通块只有1个点,那就不满足要求(没有相邻的点了),输出NIE然后退出。全部连通块都染完了,就输出TAK和每个点的颜色(K或S)。标签打了个二分图染色,其实是不是二分图无所谓了,搜索过程遇到颜色冲突了不用管,把那条边跳过,最后全部染完就成。
源代码
1 #include<queue> 2 #include<stdio.h> 3 4 int n,m; 5 struct Edge{ 6 int nxt,to; 7 }e[1000010]; 8 int head[200010],cnt=1; 9 void add(int u,int v) 10 { 11 e[cnt]={head[u],v}; 12 head[u]=cnt++; 13 } 14 bool vis[200010]; 15 bool col[200010];//颜色 16 int bfs(int x) 17 { 18 std::queue<int> q; 19 q.push(x); 20 vis[x]=1; 21 int num=1; 22 col[x]=1; 23 while(!q.empty()) 24 { 25 int u=q.front(); 26 q.pop(); 27 for(int i=head[u];i;i=e[i].nxt) 28 { 29 int v=e[i].to; 30 if(vis[v]) continue; 31 vis[v]=1; 32 col[v]=!col[u]; 33 q.push(v); 34 num++; 35 } 36 } 37 return num; 38 } 39 40 int main() 41 { 42 scanf("%d%d",&n,&m); 43 for(int i=1,j,k;i<=m;i++) 44 { 45 scanf("%d%d",&j,&k); 46 add(j,k); 47 add(k,j); 48 } 49 for(int i=1;i<=n;i++) 50 { 51 if(vis[i]) continue; 52 if(bfs(i)==1) 53 { 54 puts("NIE"); 55 return 0; 56 } 57 } 58 puts("TAK"); 59 for(int i=1;i<=n;i++) 60 { 61 puts(col[i]?"K":"S"); 62 } 63 return 0; 64 }