Werewolf

                                         Werewolf

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 262144/262144K (Java/Other)

Total Submission(s) : 1   Accepted Submission(s) : 1

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: $ 1 \leq T \leq 10 $ $ 1 \leq N \leq 100,000 $ $ 1 \leq x \leq N $ $ S \in $ {"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

 

 

Source

2018 Multi-University Training Contest 6

先說題意,在狼人殺遊戲中,有兩種角色,一種是狼人另一種是村民,他們的特徵是:

村民不會說謊
狼人可能說謊
然後玩家有三種類型:

玩家在所有的情況下只能當村民
玩家在所有的情況下只能當狼人
玩家既可以當狼人也可以當村民
題目給出nn個玩家,然後給出若干條信息,例如”xxx說xxx是狼人”或者”xxx說xxx是村民”,現在題目想請你確定,第一種類型和第二中類型的玩家數量

給一個場上出的樣例,1說2是農民,2說1是狼人。這樣的話,可以判斷出1一定是狼人,因爲若1是農民,講真話,2也是農民,講真話,1是狼人,矛盾了。

再者說,1說2是農民,2說3是農民,3說4是農民,4說1是狼人,那麼1一定是狼人,證明同上。

於是我們可以給出一個推廣,如果你被一個人認定是狼人,並且這個人還是你認定的農民,或者是被你間接認定的農民,那麼,你一定是狼

再者,如果判斷出我是狼人,那麼說我是農民的人也一定是狼人。

因此,到這裏這個題就可以寫了。

我們使用並查集來寫,剛開始我們只連接進去農民邊,記錄出來狼人邊,最後加進去狼人邊,如果狼人邊的兩端在同一個並查集內,則會產生狼人,首先被認定的人是狼人,其次,指向我的人是狼人,代碼中v數組記錄是都有誰指向我是農民,fa[]記錄的是我指向的下一個人,Q用來尋找指向我是農民的人。如果狼人邊的兩端在不同的並查集,可以忽略不管,爲什麼呢,因爲咱們假如x認定y是狼人,但是y在另一個並查集中,此時咱們想如果只有y是狼人,此時x整個並查集中時農民,y並查集中有狼人,這樣式成立的,但是如果x並查集中是狼人,y並查集中時農民,答案也是成立的,因此這種情況下,沒有一定的狼人
 

#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
const int maxn=100005;
int t,n,fa[maxn];
int ans;
vector <int> V, v[maxn];
queue<int> Q;

void init()
{
    ans = 0;
    V.clear();
    for(int i = 1 ; i <= n ; i++)
    {
        fa[i] = i;
        v[i].clear();
    }
    while(!Q.empty())
        Q.pop();
}

int Find(int x)
{
    if(x==fa[x])
    {
        return x;
    }
    return fa[x]=Find(fa[x]);
}
void un(int u,int v)
{
    int fu,fv;
    fu = Find(u);
    fv = Find(v);
    if(fu != fv)
        fa[fu] = fv;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        init();
        int tmp;
        char s[20];
        for(int i = 1; i <=n ;i++)
        {
            scanf("%d",&tmp);
            scanf("%s",s);
            if(s[0]=='v')
            {
                un(i,tmp);
                v[tmp].push_back(i);
            }
            else
            {
                V.push_back(i);
                V.push_back(tmp);
            }
        }
        for(int i = 0 ; i <= V.size() -1 ;i++)
        {
            int a,b;
            a = V[i];
            b = V[++i];
            if(Find(a)==Find(b))
            {
                Q.push(b);
                while(!Q.empty())
                {
                    int f = Q.front();
                    Q.pop();
                    ans++;
                    for(int j = 0 ; j < v[f].size();j++)
                        Q.push(v[f][j]);
                }

            }
        }
        if(n==1)
            printf("0 0\n");
        else
            printf("0 %d\n",ans);
    }
    return 0;
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章