HDU 6370 Werewolf (骚)

题目链接 有一群人,每个人可能是村民也可能是狼。村民必然说真话,狼有可能说假话。每一个人都指认了另外一个人是村民/狼,问一定是村民、一定是狼的人有多少个。

考虑狼是随机说真话或者假话,那么令每个人都为狼,一定存在一个解。因此一定是村民的数目为0。

考虑只连村民边,这样会产生若干个联通分量。可以得出这些联通分量要么是基环树,要么是树。加入狼边以后,这些联通分量必然也只可能是基环树或树。加入狼边的时候,如果这条狼边连接的是两个不同的联通分量,那么完全可以让被指向的联通分量都为狼,这个人就可能是个村民,所以被指向的人不一定为狼,这时狼边在新的连通分量中显然是树边,也就是非环的边。

如果这条狼边的两个端点在同一个连通分量之内,用反证法可以证明,被指向的人必然是狼。同时指认这个人为村民的人自然也必然是狼。此时狼边在新的联通分量中显然是基环树的环中的某一条边。

于是我们就可以在初始的时候只连反向村民边,用并查集维护联通分量,然后依次对狼边判断所指向的人是否为狼,并搜索出其余必为狼的人。

/*ргргрг*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 200050;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;

int kase, n, x, no, ans;
int head[maxn], pre[maxn];
char s[15];
struct node
{
    int to, nxt;
}e[maxn];
struct point
{
    int u, v;
};

void add(int a, int b)
{
    e[no].to = b;
    e[no].nxt = head[a];
    head[a] = no++;
}

int Find(int x)
{
    if(x == pre[x]) return x;
    return pre[x] = Find(pre[x]);
}

void dfs(int u)
{
    ans++;
    for(int i = head[u];i != -1;i = e[i].nxt)
    {
        int v = e[i].to;
        dfs(v);
    }
}

int main()
{
    scanf("%d", &kase);
    while(kase--)
    {
        scanf("%d", &n);
        no = 0;
        memset(head, -1, sizeof(head));
        for(int i = 1;i <= n;i++) pre[i] = i;
        queue<point>q;
        for(int i = 1;i <= n;i++)
        {
            scanf("%d%s", &x, s);
            if(s[0] == 'w')
            {
                point st;
                st.u = i, st.v = x;
                q.push(st);
            }
            else
            {
                add(x, i);
                int fa = Find(x), fb = Find(i);
                if(fa != fb) pre[fa] = fb;
            }
        }
        ans = 0;
        while(!q.empty())
        {
            point now = q.front();
            q.pop();
            int fu = Find(now.u), fv = Find(now.v);
            if(fu != fv) continue;
            dfs(now.v);
        }
        printf("0 %d\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/NPU_SXY/article/details/81630885