http://acm.hdu.edu.cn/showproblem.php?pid=6370
题意:
有n个人玩狼人杀。每个人都会发言 内容是 x是werewolf(狼) 或者 x是villager(村民)。村民不会说谎,狼可说谎也可不说谎。每个人都不能说自己。求最终可以确定多少个村民和多少只狼。
思路:
因为狼可以说真话说假话,那么肯定无法确定是否为村民,所以可以确定的村民的数量为0
在一个只有一条“werewolf”边的环中,被指认为“werewolf”的人肯定为狼
指认狼为村民的人也为狼
暴力找环,然后确定是否有狼,再通过这狼找到其他狼。(这是队友的代码)
#include<bits/stdc++.h>
using namespace std;
vector<int>p[111111];
int ta[111111][2];
int T;
char s[16];
int pa[111111];
int ans;
int dfs(int x)
{
if(p[x].size()==0)return 0;
int ans1=p[x].size();
for(int i=0;i<p[x].size();i++)
{
ans1+=dfs(p[x][i]);
}
return ans1;
}
bool vis[111111];
int main()
{
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
p[i].clear();
ans=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
int id;
scanf("%d %s",&id,s);
if(s[0]=='w')
{
ta[i][0]=id;
ta[i][1]=1;
}
else{
ta[i][0]=id;
ta[i][1]=0;
p[id].push_back(i);
}
}
for(int i=1;i<=n;i++)
{
if(vis[i]==0)
{
int id=i;
vis[i]=1;
int js=0;
pa[js++]=i;
while(vis[ta[id][0]]==0)
{
vis[ta[id][0]]=1;
pa[js++]=ta[id][0];
id=ta[id][0];
}
int wz=-1;
for(int j=0;j<js;j++)
{
if(pa[j]==ta[id][0])
wz=j;
}
if(wz!=-1)
{
int sum=0;
int idd=0;
for(int j=wz;j<js;j++)
{
sum+=ta[pa[j]][1];
if(ta[pa[j]][1]==1)
{
idd=ta[pa[j]][0];
}
}
if(sum==1)
{
ans++;
ans+=p[idd].size();
for(int j=0;j<p[idd].size();j++)
{
ans+=dfs(p[idd][j]);
}
}
}
}
}
cout<<"0 "<<ans<<endl;
}
return 0;
}