【HDU 6370】暑期多校day6 Werewolf (推理 基环树)

题目大意

有 n 个人在玩只有狼人和村民两种身份的狼人杀,他们在互相指认,形式为“ x 是狼人/村民”。限制:1)每个人都不能指认自己,2)村民必须说真话,3)狼人可能说谎。对于每组测试数据,要求输出一定为村民的玩家数目,一定为狼人的玩家数目。
http://acm.hdu.edu.cn/showproblem.php?pid=6370


解题思路

根据题意可知,村民只能说实话,而狼人既可以说实话又可以说谎,所以任何一个说实话的村民被替换为狼人,都会新出现一种可行解。因此在所有情况下,“一定为村民的玩家”数目必为0。那么问题就转化为:求”一定为狼人的玩家”数目,既求”一定会说谎的玩家”数目,也就是求”一定不是说实话”的玩家数目。

接下来分析:为什么有些玩家“一定不是说实话”。出现这种情况的原因一定是:如果某玩家说的是真话,那么就会出现自相矛盾的情况——形如: a 指证 b 玩家是村民,b 玩家指证 c 玩家是村民,而 c 玩家指证 b 玩家是狼人,那么 a、b 就必然是狼人,因为他们的指证与产生的间接指证产生了矛盾。既如果某个人被“他直接或间接指证为村民的人”指证是狼人,那么他本人,以及所有“直接或间接指证他为村民的人”都一定没有说实话。

由题目性质可知,每个玩家只能指认一个其他玩家。所以如果以一个“指认他人是狼人”的玩家 x 为根,可以构造出一个由“直接指认或间接指认 x 玩家为村民”的玩家构成的树,结点间以指认关系连边。那么如果某个根指认的狼人 y 是它的后代结点,以这个“被指认为狼人的玩家的结点 y ”为根的子树上的所有玩家就一定没有说实话。因为这颗子树上的玩家,都同时指证或间接指证“x 和 y 都是村民”,而 x 认为 y 是狼人,所以都会自相矛盾。

本机测官方数据会爆栈的,交上去测吧。


代码

#include <bits/stdc++.h>
using namespace std;

const int maxn=int(1e5)+111;
int n, ans=0;
int pt[maxn];
vector<int> to[maxn];

void init() {
    register int i;
    for(ans=0,i=1;i<=n;++i) {
        pt[i]=false;
        to[i].clear();
    }
    return;
}

void dfs(int pt_cur,int k,bool flag) {
    if(pt_cur==k) flag=true;
    ans+=flag;
    for(int i=0;i<(int)to[k].size();++i)
        dfs(pt_cur,to[k][i],flag);
    return;
}

void work() {
    scanf("%d",&n);
    init();
    register int i,x;
    char s[11];
    for(i=1;i<=n;++i) {
        scanf("%d%s",&x,s);
        if(s[0]=='w') pt[i]=x;
        else to[x].push_back(i);
    }
    for(i=1;i<=n;++i) if(pt[i])
        dfs(pt[i],i,0);
    printf("%d %d\n",0,ans);
    return;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    freopen("output.txt","w",stdout);
#endif
    int T;
    for(scanf("%d",&T);T;T--)
        work();

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值