zoukankan      html  css  js  c++  java
  • HDU 6370 dfs+并查集

    Werewolf

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
    Total Submission(s): 1381    Accepted Submission(s): 386


    Problem Description
    "The Werewolves" is a popular card game among young people.In the basic game, there are 2 different groups: the werewolves and the villagers.

    Each player will debate a player they think is a werewolf or not. 

    Their words are like "Player x is a werewolf." or "Player x is a villager.".

    What we know is :

    1. Villager won't lie.

    2. Werewolf may lie. 

    Of cause we only consider those situations which obey the two rules above. 

    It is guaranteed that input data exist at least one situation which obey the two rules above.

    Now we can judge every player into 3 types :

    1. A player which can only be villager among all situations, 

    2. A player which can only be werewolf among all situations.

    3. A player which can be villager among some situations, while can be werewolf in others situations.

    You just need to print out the number of type-1 players and the number of type-2 players. 

    No player will talk about himself.
     
    Input
    The first line of the input gives the number of test cases T.Then T test cases follow.

    The first line of each test case contains an integer N,indicating the number of players.

    Then follows N lines,i-th line contains an integer x and a string S,indicating the i-th players tell you,"Player x is a S."

    limits:

    1T10

    1N100,000

    1xN

    S {"villager"."werewolf"}
     
    Output
    For each test case,print the number of type-1 players and the number of type-2 players in one line, separated by white space.
     
    Sample Input
    1
    2
    2 werewolf
    1 werewolf
     
    Sample Output
     
    0 0

     解析    题解说的还是比较明白的,村名的数量一定是0  存在铁狼只有一种情况   (狼人边指向树中某个节点)

    思路就是 找所有   除了根节点指出的边是狼人边   其他节点指出的边都是好人边组成的基环树   狼人边所指的那个子树大小就是铁狼的数量

    比如 2,3,1,4,5,6 是满足条件的 基环树  铁狼的个数就是  sz[4]=4 (方框指向的是另一个联通块 所以不存在铁狼)

    只有n条边  并查集  dfs 标记什么的 搞一搞 就过了

    AC代码   写的太丑了

     1 #include <bits/stdc++.h>
     2 #define mp make_pair
     3 #define pb push_back
     4 #define fi first
     5 #define se second
     6 #define all(a) (a).begin(), (a).end()
     7 #define fillchar(a, x) memset(a, x, sizeof(a))
     8 #define huan printf("
    ");
     9 #define debug(a,b) cout<<a<<" "<<b<<" "<<endl;
    10 using namespace std;
    11 typedef long long ll;
    12 const ll maxn=1e5+20,inf=1e18;
    13 const ll mod=1e9+7;
    14 vector<pair<int,int> > g[maxn],gg[maxn];
    15 int vis[maxn],sz[maxn];
    16 int par[maxn];
    17 int _find(int x)
    18 {
    19     return x==par[x]?x:par[x]=_find(par[x]);
    20 }
    21 void unio(int a,int b)
    22 {
    23     int ra=_find(a);
    24     int rb=_find(b);
    25     if(ra!=rb)
    26         par[rb]=ra;
    27 }
    28 void dfs2(int x)//把 子树的大小求出来 并且把树归到一个集合 
    29 {
    30     sz[x]=1;vis[x]=1;
    31     for(int i=0;i<gg[x].size();i++)
    32     {
    33         pair<int,int> it=gg[x][i];
    34         if(vis[it.fi]==0)
    35         {
    36             dfs2(it.fi);
    37         }
    38         unio(x,it.fi);
    39         sz[x]+=sz[it.fi];
    40     }
    41 }
    42 char s[20];
    43 int main()
    44 {
    45     int t,n;
    46     scanf("%d",&t);
    47     while(t--)
    48     {
    49         scanf("%d",&n);
    50         int temp1,temp2;
    51         for(int i=1;i<=n;i++)
    52         {
    53             g[i].clear(),gg[i].clear();
    54             par[i]=i;
    55             vis[i]=sz[i]=0;
    56         }
    57         for(int i=1;i<=n;i++)
    58         {
    59             scanf("%d%s",&temp1,s);
    60             if(s[0]=='w')temp2=0;
    61             else temp2=1;
    62             g[i].pb(mp(temp1,temp2));
    63             if(temp2==1)
    64                 gg[temp1].pb(mp(i,temp2));
    65         }
    66         int ans=0;
    67         for(int i=1;i<=n;i++)
    68         {
    69             if(vis[i]==0&&gg[i].size()>0)//没被访问过 且有子节点
    70                 dfs2(i);
    71         }
    72         for(int i=1;i<=n;i++)
    73         {
    74             if(_find(g[i][0].fi)==_find(i)&&g[i][0].se==0)//指出的是狼边  且狼边指向自己所在的树
    75                 ans+=sz[g[i][0].fi];
    76         }
    77         printf("0 %d
    ",ans);
    78     }
    79 }
    80 
    81 //4 v 1
    82 //1 v 2
    83 //1 v 3
    84 //5 v 4
    85 //6 v 5
    86 //4 w 6
    87 //4 w 7
    88 //6 v 8
    89 //10
    90 //8
    91 //4 v
    92 //1 v
    93 //1 v
    94 //5 v
    95 //6 v
    96 //4 w
    97 //4 w
    98 //6 v
  • 相关阅读:
    【转载】Android应用框架及常用工具类总结
    【Android】Android开发规范的一点小体会
    【Android】解决Android的ListView控件滚动时背景变黑
    【Android】侧边栏SlidingMenu
    【Android】解决RadioButton+FragmentPagerAdapter+Fragment切换页面数据加载的问题
    【Android】ListView动态视图显示不全
    Android编码规范
    【Android】两个日期相差几天和两个日期比较大小
    Linux基础之快照克隆、Xshell优化、Linux历史
    Android APP打包时,出错:"XXX" is not translated in "af" (Afrikaans), "am" (Amharic)
  • 原文地址:https://www.cnblogs.com/stranger-/p/9450821.html
Copyright © 2011-2022 走看看