杭电多校第六次 HDU6370 Werewolf(记忆化搜索)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ffgcc/article/details/81543003

Werewolf
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1443 Accepted Submission(s): 395

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≤T≤10

1≤N≤100,000

1≤x≤N

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

大佬卡题,题卡我
这道题有思路,但却硬生生的WA了好多次。。
emmmmm…
解析:
全部是狼人满足所有情况
所以确定为村民的个数为0
所以可以想到通过dfs判断一定是狼的个数,
我们以村民为边建图,如果有狼回到了村民,那么就把前半部分设置为狼,后面则可以是村民
为了防止超时,还要记忆化一下,记忆化的过程代码中有注释

#include<bits/stdc++.h>
using namespace  std;
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define mod 1000000007
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
const int N=1e5+10;
int vis[N];
int ri[N];
int du[N];
int sum3=0,pp=-1,flag=1;
void dfs(int now)
{
    vis[now]=-2;
    if(ri[now]>0)
    {
        int a=ri[now];
        if(vis[a]==0)//没有搜索过,继续搜
            dfs(a);
        else if(vis[a]==-1) pp=now;//搜索到了狼
        else pp=vis[a];//搜索到了村民,就要找
        //村民最末端的狼,如果狼在这个环内,那么显然pp
        //之前的都是狼,否则都可以是村民
    }
    else
    {
        int a=-ri[now];//出现狼的边,直接记录一下就好
            pp=a;
    }
    if(now==pp) flag=0;
    if(!flag) vis[now]=-1;
    else vis[now]=pp;
}
int main()
{
    #ifdef local
        freopen("D://rush.txt","r",stdin);
    #endif
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    string s;
    while(t--)
    {
        memset(vis,0,sizeof vis);
        memset(ri,0,sizeof ri);
        sum3 =0;
        int n,a;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a>>s;
            if(s[0]=='v')
                ri[i]=a;
            else
                ri[i]=-a;
        }
        for(int i=1;i<=n;i++)
        {
            if(vis[i]==0)
            {
                pp=-1,flag=1;
                dfs(i);
            }
        }
        rep(i,1,n)
            if(vis[i]==-1) sum3++;
        printf("0 %d\n",sum3);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ffgcc/article/details/81543003