HDU 6370(思维)

淩亂°似流年 2022-05-17 11:06 218阅读 0赞

传送门

思路:因为狼说什么都是可以的,所以全是狼是可以,村民为0。

那问题就是转化成求铁狼的数量。我们对村民边建图,我们发现,一个连通分量要么是个基环树,要么是个树。对于基环树全是村民的话显然成立。所以不存在铁狼。对于树,必然有且仅有一个点连出去的是狼边,①如果这条边指向其他连通分量,其他联通分量完全可以都是狼,那这个人就可能是个人,所以他不是铁狼。②如果指向自己的连通分量,如果他是狼,那么这个联通分量都是狼(因为都说了假话),如果他是人,那么从它指向的节点到它可能是狼可能是人,只有其他节点才是铁狼。所以用并查集判断连通分量,再往上搜索找出狼的个数就可以了。

另外,真的想吐槽HDU,自己手残将1e5写成105,结果它不给我判re,却判TLE

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N=1e6+10;
  4. struct node{
  5. int to;
  6. char ch;
  7. }e[N];
  8. vector<int> fa[N];
  9. int f[N], n, ans;
  10. int _find(int x){
  11. return f[x]==x?x:f[x]=_find(f[x]);
  12. }
  13. void conbine(int x, int y){
  14. int tx=_find(x), ty=_find(y);
  15. if(tx!=ty){
  16. f[tx]=f[ty];
  17. }
  18. }
  19. void count_ans(int x){
  20. ans++;
  21. for(int i=0; i<fa[x].size(); i++)
  22. count_ans(fa[x][i]);
  23. }
  24. int main(){
  25. int T;
  26. scanf("%d", &T);
  27. while(T--){
  28. ans=0;
  29. scanf("%d", &n);
  30. char s[100];
  31. for(int i=1; i<=n; i++)
  32. fa[i].clear();
  33. for(int i=1; i<=n; i++)
  34. f[i]=i;
  35. int v ;
  36. for(int i=1; i<=n; i++){
  37. scanf("%d %s", &v, s);
  38. e[i].to=v; e[i].ch=s[0];
  39. if(s[0]=='v'){
  40. conbine(i, v);
  41. fa[v].push_back(i);
  42. }
  43. }
  44. for(int i=1; i<=n; i++){
  45. int to=e[i].to;
  46. char ch=e[i].ch;
  47. if(ch=='w'){
  48. if( _find(i)==_find(to))
  49. count_ans(to);
  50. }
  51. }
  52. printf("0 %d\n", ans);
  53. }
  54. return 0;
  55. }

发表评论

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

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

相关阅读

    相关 HDU 6370(思维)

    [传送门][Link 1] 思路:因为狼说什么都是可以的,所以全是狼是可以,村民为0。 那问题就是转化成求铁狼的数量。我们对村民边建图,我们发现,一个连通分量要么是个基环树