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
  • 相关阅读:
    Linux下zip命令使用
    docker镜像发布到阿里云镜像仓库
    基于官方镜像定制php-fpm容器
    docker-compose部署开发环境
    docker安装discuz!Q
    从零开始实现简单 RPC 框架 4:注册中心
    从零开始实现简单 RPC 框架 3:配置总线 URL
    从零开始实现简单 RPC 框架 2:扩展利器 SPI
    从零开始实现简单 RPC 框架 1:RPC 框架的结构和设计
    文本分类(六):pytorch实现DPCNN
  • 原文地址:https://www.cnblogs.com/stranger-/p/9450821.html
Copyright © 2011-2022 走看看