版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/V5ZSQ/article/details/82562808
Description
个人在玩儿狼人杀,给出每人的发言,即 说 是狼人或村民,已知村民只能说真话,而狼人可以说真话可以说假话,问一定可以确认身份的村民数量和狼人数量
Input
第一行一整数 表示用例组数,每组用例首先输入一整数 表示人数,之后 行分别表示每个人的发言
Output
输出一定可以确认身份的村民数量和狼人数量
Sample Input
1
2
2 werewolf
1 werewolf
Sample Output
0 0
Solution
由于狼人也可以说真话,故无法判断出村民的身份,但是若 说 是狼人而 说 是村民,则无论 是狼人还是村民 都是狼人,进一步的,对于一个环 ,若 说 是狼人,而其他人都判断下一个人是村民,那么 必然是狼人,故问题转化为找每个环上的 ,在以此判断出狼人后,所有说狼人是村民的必然也是狼人,故以判断村民关系反向建图 一遍就找到了所有狼人
Code
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
#define maxn 100005
int T,n,wolf[maxn],e[maxn][2],vis[maxn];
vector<int>g[maxn];
void dfs(int u,int tag)
{
vis[u]=tag;
int v=e[u][0],type=e[u][1];
if(vis[v])
{
if(vis[v]!=tag)return ;
int temp=0;
int p=v;
while(1)
{
if(e[p][1])
{
if(temp==0)temp=e[p][0];
else temp=-1;
}
p=e[p][0];
if(p==v)break;
}
if(temp>0)wolf[temp]=1;
return ;
}
dfs(v,tag);
}
int dfs1(int u)
{
vis[u]=1;
for(int i=0;i<g[u].size();i++)
if(!vis[g[u][i]])dfs1(g[u][i]);
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
char op[11];
scanf("%d%s",&e[i][0],op);
if(op[0]=='w')e[i][1]=1;
else e[i][1]=0;
}
memset(vis,0,sizeof(vis));
memset(wolf,0,sizeof(wolf));
for(int i=1;i<=n;i++)
if(!vis[i])dfs(i,i);
int ans=0;
for(int i=1;i<=n;i++)g[i].clear();
for(int i=1;i<=n;i++)
if(!e[i][1])g[e[i][0]].push_back(i);
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
if(!vis[i]&&wolf[i])dfs1(i);
for(int i=1;i<=n;i++)ans+=vis[i];
printf("0 %d\n",ans);
}
return 0;
}