本文主要是介绍HDU6370 Werewolf(2018HDU多校联赛第六场,思路,dfs),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
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 n <script type="math/tex" id="MathJax-Element-1">n</script>个玩家,然后给出若干条信息,例如”xxx说xxx是狼人”或者”xxx说xxx是村民”,现在题目想请你确定,第一种类型和第二中类型的玩家数量
首先我们知道,因为狼人可以说谎,所以假设所有的玩家全部是狼人,不论谁说谁是什么,游戏一定成立,他们都可以当狼人,也就证明了不存在“玩家在所有的情况下只能当村民”这种情况.
那么,我们可以做一个假设,假设全部的玩家都是狼人,那么第二种玩家类型的数量为总的玩家数量减去狼人中可以当村民的玩家数量。
那么问题就转化成了在所有的玩家都是狼人的时候,有多少人可以当村名。
我们可以先对题目给出的数据进行记录,记录一下每个人谁说他是狼人和谁说他是村民的玩家数量。
我们首先对每一个玩家进行处理,比如,当玩家2说玩家1是狼人的时候,假设玩家1就是狼人,那么当玩家1是狼人的时候他不管说什么,都可以使游戏成立.这个时候我们就可以确定,玩家2可以当村民,那么玩家2当了村民,那么谁说玩家2是村民,那么这个人也可以当村民,这是一个递归的过程,在过程中用vis数组标记当前玩家已经有了确定的身份。但是在这个递归的过程中要注意,当递归出现环的时候,假设到了玩家5,玩家1说玩家5是村民,这个时候因为玩家1的身份是我们确定了的狼,所以玩家1不能被标记为村民,而且要把所有说玩家1是村民的玩家都标记一下。
最后我们就知道了这些狼人中哪些玩家可以做村民,然后用总数减去,再把所有玩家遍历一遍,减去没有被标记过的玩家,就是答案。
代码
#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
const int N = 1e5 + 100;
/*
v1[i]:说第i个人是狼人的集合
v2[i]:说第i个人是村民的集合
*/
vector<int> v1[N], v2[N];
int vis[N];
void init()
{mem(v1, 0);mem(v2, 0);mem(vis, 0);
}
void dfs2(int u)
{for (auto num : v2[u]){vis[num] = 1;dfs2(num);}
}
int dfs(int u, int i)
{int ans = 0;for (auto num : v2[u]){vis[num] = 1;if (num != i)ans += dfs(num, i);elsedfs2(num);}return ans + 1;
}
void solve()
{int n, x;char s[10];scanf("%d", &n);init();for (int i = 1; i <= n; i++){scanf("%d%s", &x, s);if (s[0] == 'w')v1[x].push_back(i);elsev2[x].push_back(i);}int ans = 0;for (int i = 1; i <= n; i++){for (auto num : v1[i]){vis[num] = 1;ans += dfs(num, i);}}ans = n - ans;for (int i = 1; i <= n; i++){if (!vis[i])ans--;}printf("0 %d\n", ans);
}
int main()
{// freopen("in.txt", "r", stdin);int t;scanf("%d", &t);while (t--)solve();return 0;
}
这篇关于HDU6370 Werewolf(2018HDU多校联赛第六场,思路,dfs)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!