2016ACMICPC亚洲区大连站重现赛1001 Wrestling Match

待我称王封你为后i 2022-07-15 09:11 239阅读 0赞

菜鸟写题,多多指教

HDU 5971Wrestling Match

题意 :n(<=1000)个人,其中有个x好人,y个坏人m(<=10000)场比赛,胜者为好人,负者为坏人

问能通过这些比赛是否可能将所有人分为好人或坏人。也就是每个人都有一状态,并且和比赛不冲突;

//输入

n m x y

5 4 1 0

//对手,也就是关系

a b

1 3

1 4

3 5

4 5

//x个好人的列表

2

//y个坏人的列表

//输出

YES

遍历所有相关集,所有集合都满足 (状态不冲突,所有人有状态) 则输出YES;

遍历参数是相关集,每个集合最多两种情况,

确定一个人可以确定相关集里的所有人;

vector c[1010]存关系;

int a[1010] 存状态;

set s[1010]存集合

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int main()
  4. {
  5. int n,m,x,y;
  6. //freopen("in.txt","r",stdin);
  7. while(scanf("%d%d%d%d",&n,&m,&x,&y)!=EOF)
  8. {
  9. vector<int> c[1010];//关系
  10. int ac[1010];//状态,ac[0]不存
  11. memset(ac,0,sizeof(ac));
  12. int k = 0;//集合数
  13. set<int> s[1010];
  14. for(int ii = 0; ii < m; ii++){
  15. int a,b;
  16. scanf("%d%d",&a,&b);
  17. c[a].push_back(b);
  18. c[b].push_back(a);
  19. int ka = 0,kb = 0;//a,b所在集合,没有为0;
  20. for(int i = 1; i <= k; i++){
  21. if(s[i].find(a)!= s[i].end()) ka = i;
  22. if(s[i].find(b)!= s[i].end()) kb = i;
  23. }
  24. if(!ka && !kb){ //a,b都没有所属集合
  25. k++;
  26. s[k].insert(a);
  27. s[k].insert(b);
  28. }
  29. else if(!ka) //a没有所属集合
  30. s[kb].insert(a);
  31. else if(!kb) //b没有
  32. s[ka].insert(b);
  33. else if(ka != kb){ //a,b都有,合并两集合并s[ka]标记为无效
  34. if(s[ka].size() > s[kb].size()) swap(ka,kb);
  35. set<int>::iterator it;
  36. for(it = s[ka].begin(); it != s[ka].end(); it++)
  37. s[kb].insert(*it);
  38. s[ka].clear();
  39. s[ka].insert(-10);
  40. }
  41. }
  42. /*
  43. for(int i = 1; i <= k; i++)//print all sets
  44. {
  45. cout<<i<<": ";
  46. for(set<int>::iterator it = s[i].begin(); it != s[i].end(); it++)
  47. {
  48. cout<<*it<<" ";
  49. }
  50. cout<<endl;
  51. }
  52. */
  53. for(int i = 0; i < x; i++)
  54. {
  55. int a;
  56. scanf("%d",&a);
  57. ac[a] = 1;
  58. }
  59. for(int i = 0; i < y; i++)
  60. {
  61. int a;
  62. scanf("%d", &a);
  63. ac[a] = -1;
  64. }
  65. //cout<<k<<endl;
  66. int ok = 1;
  67. for(int i = 1; i <= k; i++)///visit sets;
  68. {
  69. set<int>::iterator it = s[i].begin();
  70. if(*it == -10) continue;
  71. for(it; it != s[i].end(); it++)
  72. {
  73. if(ac[*it]) break;
  74. }
  75. if(it == s[i].end())//集合中没有已经确定的元素;假设一种状态
  76. {
  77. it = s[i].begin();
  78. ac[*it] = 1;
  79. //cout<<*it<<" "<<i<<" "<< -ac[*it]<<" **"<<endl;
  80. }
  81. int tip[1010]; //是否已经被访问不能仅从ac[] == 0来判断
  82. memset(tip,0,sizeof(tip));
  83. queue<int> q;
  84. q.push(*it);
  85. while(!q.empty())
  86. {
  87. int q1 = q.front();
  88. q.pop();
  89. if(tip[q1]) continue;
  90. else tip[q1] = 1;
  91. for(int i = 0; i < c[q1].size(); i++)
  92. {
  93. if(!ac[c[q1][i]])//对手没有性质
  94. {
  95. ac[c[q1][i]] = -ac[q1];
  96. q.push(c[q1][i]);
  97. }
  98. else if(ac[c[q1][i]] == ac[q1])
  99. {
  100. ok = 0; //对手和自己性质相同
  101. //cout<<q1<<" == "<<c[q1][i]<<endl;
  102. break;
  103. }
  104. else
  105. {
  106. q.push(c[q1][i]);
  107. }
  108. }
  109. if(!ok) break; //已经违反,不再进行循环
  110. }
  111. }
  112. for(int i = 1; i <= n; i++)
  113. {
  114. //cout<<ac[i]<<" x"<<endl;
  115. if(!ac[i])
  116. {
  117. ok = 0;
  118. //break;
  119. }
  120. }
  121. if(ok) cout<<"YES"<<endl;
  122. else cout<<"NO"<<endl;;
  123. }
  124. return 0;
  125. }

发表评论

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

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

相关阅读