hdu 6370 Werewolf

Werewolf

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 1154    Accepted Submission(s): 314

Problem Description

"The Werewolves" is a popular card game among young people.In the basic game, there are 2 different groups: the werewolves and the villagers.
Each player will debate a player they think is a werewolf or not. 
Their words are like "Player x is a werewolf." or "Player x is a villager.".
What we know is :
1. Villager won't lie.
2. Werewolf may lie. 
Of cause we only consider those situations which obey the two rules above. 
It is guaranteed that input data exist at least one situation which obey the two rules above.
Now we can judge every player into 3 types :
1. A player which can only be villager among all situations, 
2. A player which can only be werewolf among all situations.
3. A player which can be villager among some situations, while can be werewolf in others situations.
You just need to print out the number of type-1 players and the number of type-2 players. 
No player will talk about himself.

Input

The first line of the input gives the number of test cases T.Then T test cases follow.
The first line of each test case contains an integer N,indicating the number of players.
Then follows N lines,i-th line contains an integer x and a string S,indicating the i-th players tell you,"Player x is a S."
limits:
1≤T≤10
1≤N≤100,000
1≤x≤N
S∈ {"villager"."werewolf"}

Output

For each test case,print the number of type-1 players and the number of type-2 players in one line, separated by white space.

Sample Input

1 2 2 werewolf 1 werewolf

Sample Output

0 0

题意 : 狼人游戏。狼人可能说谎,村民不会说谎。N个人每个人说一句话,“x是狼人”或者“x是村民”。 
求一定是村民的人的数量,一定是狼人的人的数量。

题解

1:因为狼人可以不说谎,即狼人可以伪装成村民,故不存在一定是村民的人。 
2:然后,如果A说B是村民,B说A是狼人,那么A一定是狼人。(因为如果A是村民 , 那么 B 也是村民,那么B 说的是实话 : A 是 狼人,所以不符合假设,所以 A 一定是狼人。)

3:同理可得 ,如果A说B是村民,B说C是村民,C说A是狼人,那么A一定是狼人。总而言之,一个N条边的环,有N-1条村民边,1条狼人边,那么狼人边所指认的狼人一定就是狼人。

4:根据确定的狼人,指认狼人为村民的人也一定是狼人。

代码实现 : 可以将2 或 3 中确定的狼入队,来一遍bfs找到符合判定关系的狼。

#include <bits/stdc++.h>
using namespace std;
const int MX = 100010;
int T, n, x, y, tot, head[MX], ans, q[MX], h, t, f[MX];
bool vis[MX];
char st[30];
struct data {
	int x, role;
} a[MX];
struct node {
	int v, nxt;
} edge[MX];

void addEdge(int u, int v) {
	++tot;
	edge[tot].v = v;
	edge[tot].nxt = head[u];
	head[u] = tot;
}

int fund(int x) {
	if (f[x] == x) return f[x];
	return f[x] = fund(f[x]);
}

void join(int x, int y) {
	x = fund(x);
	y = fund(y);
	if (x == y) return;
	f[x] = y;
}

int main() {
	scanf("%d", &T);
	while (T--) {
		tot = 0;
		memset(head, 0, sizeof(head));
		memset(vis, 0, sizeof(vis));
		scanf("%d", &n);
		for (int i = 1; i <= n; ++i) {
			scanf("%d", &a[i].x);
			scanf("%s", st);
			a[i].role = st[0] == 'v' ? 1 : 0;
			if (a[i].role == 1) addEdge(a[i].x, i);
		}
		h = -1;
		t = -1;
		ans = 0;

		for (int i = 1; i <= n; i++) f[i] = i;

		for (int i = 1; i <= n; i++)
			if (a[i].role == 1)
				join(i, a[i].x);

		for (int i = 1; i <= n; ++i)
			if (fund(i) == fund(a[i].x) && a[i].role == 0) {
				q[++t] = a[i].x;
				vis[a[i].x] = 1;
				ans++;
			}

		while (h < t) {
			x = q[++h];
			for (int i = head[x]; i; i = edge[i].nxt) {
				y = edge[i].v;
				if (!vis[y]) {
					q[++t] = y;
					vis[y] = 1;
					ans++;
				}
			}
		}
		printf("0 %d\n", ans);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值