2019年湘潭大学程序设计竞赛-G Truthman or Fakeman

古城微笑少年丶 2022-01-25 16:43 233阅读 0赞

题目: 有n个人在玩一个身份扮演的游戏。 把这n个人编号为1,2,3…n。 其中每个人会扮演下面两种身份中的一种: Truthman:当某个人扮演Truthman时,这个人只会说真话。 Fakeman:当某个人扮演Fakeman时,这个人只会说假话。 这n个人是互相知道身份的,但是Casya作为一个旁观者不知道任何一个人的身份。 为了让Casya有可能推断这些人的身份,这n个人说了m句话。 每句话的内容只包含某人对某人身份的一条描述,且被Casya记录为以下形式: u,v,0 — u认为v是一个Fakeman; u,v,1 — u认为v是一个Truthman; 当然这些话不一定都是真话,这取决于说话的人的身份。 但是可以肯定的是身份只有两种,也就是说某个人不是Truthman就是Fakeman。 Casya想知道不违反上面的条件和记录最少有多少个Fakeman,除此之外他还想得到一组在此情况下的一组合理的解—即所有人的身份。或者确定记录本来就是矛盾的所以没有任何符合条件的解。

分析:如果A说B是Truthman 那么A和B是同一个团体,如果A说B是Fakeman,那么A和B是不同的两个团体,这两个条件只需在图上建立一个权值标记就行了,对于一个联通块,确定一个点的性质之后,整个联通块的每个点的性质就都确定了。只要将较大的那个定义为Truthman就好了,用dfs遍历连通块,如果一开始设为Truthman的团体较小 那就再dfs一遍取反。

补充:这题也可以用种类并查集来做,可以参考https://blog.csdn.net/weixin_43849505/article/details/90082395

https://blog.csdn.net/qq_42936517/article/details/90021825

代码:

#

  1. #include <bits/stdc++.h>
  2. const int N = 1e5 + 5;
  3. using namespace std;
  4. int t,n,m,vs[N],a[N],flag,s1,s2;
  5. struct nd{
  6. int v,w;
  7. };
  8. vector<nd> e[N];
  9. void dfs(int u) {
  10. vs[u]=1;
  11. if(a[u]) s1++;
  12. else s2++;
  13. for(int i=0;i<e[u].size();i++) {
  14. int v=e[u][i].v,w=e[u][i].w;
  15. if(!vs[v]) {
  16. if(w) a[v]=a[u];
  17. else a[v]=a[u]^1;
  18. dfs(v);
  19. }else if((w&&a[u]!=a[v])||(w==0&&a[u]==a[v])) flag=1;
  20. }
  21. }
  22. void dfs2(int u) {
  23. vs[u]=2,a[u]^=1;
  24. for(int i=0;i<e[u].size();i++) {
  25. int v=e[u][i].v;
  26. if(vs[v]==1) {
  27. dfs2(v);
  28. }
  29. }
  30. }
  31. int main () {
  32. while (~scanf("%d",&t)) {
  33. while(t--) {
  34. scanf("%d%d",&n,&m);
  35. for(int i=1;i<=n;i++) e[i].clear();
  36. memset(vs,0,sizeof(vs));
  37. memset(a,0,sizeof(a));
  38. flag=0;
  39. for(int i=1,u,v,w;i<=m;i++) {
  40. scanf("%d%d%d",&u,&v,&w);
  41. if(w) e[u].push_back({v,1}),e[v].push_back({u,1});
  42. else e[u].push_back({v,0}),e[v].push_back({u,0});
  43. }
  44. for(int i=1;i<=n;i++) {
  45. if(!vs[i]) {
  46. a[i]=1,s1=s2=0;
  47. dfs(i);
  48. if(s1<s2) dfs2(i);
  49. }
  50. }
  51. if(flag) printf("-1\n");
  52. else {
  53. for(int i=1;i<=n;i++)
  54. printf("%d",a[i]==1);
  55. printf("\n");
  56. }
  57. }
  58. }
  59. return 0;
  60. }

发表评论

表情:
评论列表 (有 0 条评论,233人围观)

还没有评论,来说两句吧...

相关阅读