Werewolf

http://acm.hdu.edu.cn/showproblem.php?pid=6370

分析:

思路:首先所有人都是狼一定合法,所以村民无法确定。经过一番推理,发现只有两种情况可以确定狼:

1、某些人的发言构成一个环,环上只有一个人发言说xxx是狼,其他的都说是村民。那么被说是狼的这个人一定是狼。

2、由1确定狼以后,有人说1确定的狼是人,那么这个人就一定是狼。(因为村民不会说谎)

暴力找环

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
const int maxn=100010;
int n,m,k;
int vis[maxn];
int id[maxn],c[maxn];
bool a[maxn];
int ans,ct,cnt,tmp,f,flag;
char s[maxn];
vector<int>vc[maxn];
queue<int>q;
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        ans=0;tmp=0;
        for(int i=1;i<=n;i++)
        {
             vis[i]=0;
             a[i]=false;
             vc[i].clear();
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&id[i]);//记录i说的编号
            scanf("%s",s);
            if(s[0]=='w') c[i]=1;
            else {c[i]=0;vc[id[i]].push_back(i);}//i说id[i]是人
            //确定出来是狼,那么说他是人的一定是狼
        }
        f=0;
        for(int i=1;i<=n;i++)
        if(!vis[i]){
            cnt=0;
            int j=id[i];
            f++;//第几个环
            vis[i]=f;
            while(1)
            {
                if(vis[j]==inf) break;//在某个环上出现了,就不找了
                if(vis[j]==f)//每个人都出一条边一定有环
                {
                        cnt=0;
                        vis[j]=inf;//每个点只能出现在一个环上,出现在某个环上标记一下
                        int k=id[j];
                        if(c[j]) cnt++;
                        while(1)
                        {
                            vis[k]=inf;
                            if(c[k]) {cnt++;flag=id[k];}
                            k=id[k];
                            if(k==j) break;
                        }
                        if(cnt==1)
                        {  
                            tmp++;a[flag]=1;
                            for(int tt=0;tt<vc[flag].size();tt++)
                            {
                                q.push(vc[flag][tt]);//说铁狼是人的那个东西的编号;他一定是狼
                            }
                        }
                    break;
                }
                //cout<<"*";
                vis[j]=f;
                j=id[j];
            }
        }
        while(!q.empty()){
        int k=q.front();q.pop();
        tmp++;
        for(int tt=0;tt<vc[k].size();tt++)
        {
            q.push(vc[k][tt]);//说铁狼是人的东西的编号;
        }
        }
        printf("%d %d\n",ans,tmp);
      //  if(flag) puts("Yes"); else puts("No");
    }
    return 0;
}
 

猜你喜欢

转载自blog.csdn.net/qq_37891604/article/details/81585056