Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0
“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 :
Villager won’t lie.
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 :
A player which can only be villager among all situations,
A player which can only be werewolf among all situations.
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.
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”}
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.
1
2
2 werewolf
1 werewolf
0 0
“狼人杀”简化版,两种角色:狼和村民;狼的话可真可假,村民的话一定为真。
看到这题我的第一反应就是——答案会不会一定是0?最后发现,这道题里,必为村民的的角色一定为0,而必为狼的角色则不一定。
1.因为谎言的存在,“这世上没有一个可信之人”。因为狼也会像村民一样说真话,所以狼可以扮演村民的角色,不存在纯粹的村民。
2.
(1)当角色A指认角色B为村民,而角色B指认角色A为狼,则我们可以确定:A一定是狼(通过反证法);
这种“被自己认定为村民的角色指认为狼”的判定狼的方法还可能存在链式的“村民指认”关系,举例来说,若A指认B是村民,B指认C是村民,C指认A是狼,则A一定是狼,B、C不确定。
由于每个角色只会指认一个角色,这可以写成并查集。
(2)当某角色指认一条确定的狼是村民是,此角色也一定是狼。可以将(1)中确定的狼入队,来一遍bfs找到符合判定关系的狼。
#include
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;
}