【图论】HDU6370 Werewolf

分析:

这题还算比较水的。。。真不知道为什么初三的小朋友被卡了。。。

明明人家初二的小朋友拿这题签到来着。。。。


显然,可以所有人都是狼人,这是一定合法的,所以一定是村民的人数必然为0

因此,只需要知道哪些人一定是狼人,就能得到答案。

我们定义一条全是由“认为xx是村民”的边,所组成的链为一条信任链。不同的信任链可以重合。

这种信任链的特点是:对某个信任链上的点而言,它认为所有它的后继节点都是村民(即A认为B是村民,B认为C是村民,等价于A认为C是村民)。且它的后继一定是一条链(即不可能分叉)。

那么一个人是狼人的条件只有2个:
1、它所在的信任链的最后一个节点认为它是狼人。
2、它的信任链的某个后继节点一定是狼人。

否则,一定存在某种方案,使得这个人为村民。

证明很简单,由于狼人可说谎可不说,我们可以假定当前这个人是村民,那必须说真话的无非就是它的信任链上的后继节点,然而这些点都一定不会矛盾(条件2),所以这个点也不会矛盾。

所以只需要存“认为xx是村民”的边,然后用“认为xx是狼人”来查询,即对每个狼人关系处理一下,判断它是否是:它所指认的人所在的信任链的最靠后的节点。

然后确定出所有满足条件1的人,然后沿着信任链反向走,把所遍历到的点都标记为狼人即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#define SF scanf
#define PF printf
#define MAXN 100010
using namespace std;
int x;
int n,ans,cnt;
bool used[MAXN],vis[MAXN];
vector<int> a[MAXN];
char s[MAXN];
int dp[MAXN];//这个点所在的信任链的最靠后的点
pair<int,int> l[MAXN];
queue<int> q;
void dfs(int x,int flag){
    dp[x]=flag;
    for(int i=0;i<a[x].size();i++){
        int v=a[x][i];
        dfs(v,flag);    
    }
}
int main(){
    int t;
    SF("%d",&t);
    while(t--){
        SF("%d",&n);
        cnt=0;
        for(int i=1;i<=n;i++){
            a[i].clear();
            used[i]=0;
            vis[i]=0;
            dp[i]=0;
        }
        for(int i=1;i<=n;i++){
            SF("%d",&x);
            SF("%s",s);    
            if(s[0]=='w'){
                l[++cnt]=make_pair(i,x);
                vis[i]=1;
            }
            else
                a[x].push_back(i);
        }
        for(int i=1;i<=n;i++)
            if(vis[i]==1){
                dfs(i,i);
            }
        for(int i=1;i<=cnt;i++){
            int u=l[i].first,v=l[i].second;
            if(u==dp[v])
                if(used[v]==0){
                    q.push(v);
                    used[v]=1;
                }
        }
        ans=0;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            ans++;
            for(int i=0;i<a[x].size();i++)
                if(used[a[x][i]]==0){
                    used[a[x][i]]=1;
                    q.push(a[x][i]);    
                }
        }
        PF("0 %d\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_34454069/article/details/81563718