HDU 6370 Werewolf 【并查集】

任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6370

Werewolf

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

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

Source

2018 Multi-University Training Contest 6

题意概括:

读题意前要清空一下记忆,这里的狼人杀和实际的狼人杀规则不太一样。

每人按顺序说出一个人的角色(不能说自己的)

1、村民一定说真话

2、狼人有可能说假话。

求:

一定是村民的数量 和 一定是狼人的数量。

解题思路:

模拟了一下,感觉并不会有村民,因为没有方案可以证明出某个人一定是村民,因为狼人有“可能”说谎。

但我们可以确认哪些一定是狼人,即存在环,环的最后是 狼人边,其余都是村民边,那么被狼人边指的一定是狼人。

而用村民边指向这个狼人的角色也一定是狼人。

那么DFS,村民边建正向边,狼人边建反向边。

遍历狼人边,判断是否存在上述的环,如果存在再继续拓展。

大佬的证明:https://blog.csdn.net/weixin_39453270/article/details/81515570

AC code:

 1 #include <bits/stdc++.h>
 2 #define INF 0x3f3f3f3f
 3 #define LL long long
 4 using namespace std;
 5 const int MAXN = 1e5+10;
 6
 7 int N, M;
 8 int w[MAXN];
 9 vector<int>fa[MAXN], son[MAXN];
10 bool vis[MAXN];
11 int ans[MAXN], cnt;
12
13 void add1(int a, int b)
14 {
15     fa[a].push_back(b);
16 }
17
18 bool dfs(int a, int b)
19 {
20     bool flag = true;
21     for(int i = 0; i < fa[a].size(); i++){
22         if(fa[a][i] == b) return false;
23         flag = dfs(fa[a][i], b);
24         if(!flag) return false;
25     }
26     return flag;
27 }
28
29 void dfs2(int x)
30 {
31     if(!vis[x]) return;
32     vis[x] = false;
33     for(int i = 0; i < fa[x].size(); i++){
34         if(vis[fa[x][i]]){
35             cnt++;
36             dfs2(fa[x][i]);
37         }
38     }
39 }
40
41 int main()
42 {
43     //freopen("6370in.txt", "r", stdin);
44     int T_case, id, tot = 0;
45     char ty[10];
46     scanf("%d", &T_case);
47     while(T_case--){
48         cnt = 0;
49         tot = 0;
50         memset(vis, 1, sizeof(vis));
51         scanf("%d", &N);
52         for(int i = 1; i <= N; i++){ fa[i].clear();son[i].clear();}
53
54         for(int i = 1; i <= N; i++){
55             scanf("%d %s", &id, &ty);
56             if(ty[0] == ‘w‘){
57                 w[++tot] = i;
58                 son[i].push_back(id);
59             }
60             else{
61                 add1(id, i);
62             }
63         }
64         for(int i = 1; i <= tot; i++){
65             if(!vis[w[i]]) continue;
66             for(int k = 0; k < son[w[i]].size();k++){
67                 if(!vis[son[w[i]][k]]) continue;
68                 if(!dfs(w[i], son[w[i]][k])){
69                     //puts("zjy");
70                     cnt++;
71                     dfs2(son[w[i]][k]);
72                 }
73             }
74         }
75
76         printf("0 %d\n", cnt);
77     }
78 }

原文地址:https://www.cnblogs.com/ymzjj/p/10436504.html

时间: 2024-10-01 22:03:08

HDU 6370 Werewolf 【并查集】的相关文章

Hdu 2473(并查集删除操作) Junk-Mail Filter

有木有很吊 加强 加强版   啊  ,看了都不敢做了   ,后来先做了食物链这个我还是看过的,但还是A不掉,没明白神魔意思 ,总而言之,大牛的博客是个好东西,我就那么看了一下,还是不懂怎莫办啊,哎,就那样就A掉了....... 今天我们来谈一下这个并查集的删除操作,根据我对大牛的理解啊,这个并查集的删除操作并不是把原来的节点删除掉,而是用一个替身替掉,现在的这个点只是用作桥梁的作用,即是无用的,del  ,,,del  ,,,,删除,那些被删掉的就从n开始给他们一个地址,然后即如下代码所示 #i

HDU 4496 D-City(并查集,逆思维)

题目 熟能生巧...常做这类题,就不会忘记他的思路了... //可以反过来用并查集,还是逐个加边,但是反过来输出...我是白痴.....又没想到 //G++能过,C++却wa,这个也好奇怪呀... #include<stdio.h> #include<string.h> int fx,fy,r,bin[10010]; int x[100010],y[100010],n,m,i,count,ans[100010],j; int find(int x) { //改成这样就不会超时了么好

HDU 1272 简单并查集

小希的迷宫 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 24915    Accepted Submission(s): 7641 Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双

hdu 3038 (并查集)

题目大意: 给出m个询问,问[l,r]之间的和   ,求出有多少次询问不和之前的矛盾的. 思路分析: 用并查集记录当前节点到根节点的和. #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #define maxn 222222 using namespace std; int set[maxn]; int sum[maxn]; int find(int

hdu 4496 D-City 并查集

D-City Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 2317    Accepted Submission(s): 814 Problem Description Luxer is a really bad guy. He destroys everything he met. One day Luxer went to D-

Farm Irrigation HDU - 1198 (并查集)

Farm Irrigation HDU - 1198 题意:给11种管道,问草地最少需要打多少个井才可以全部灌溉. 把每种管道的状态用二进制表示一下,然后对每一块草地,判断能否和上面或者左面的草地的管道连接. 然后并查集搞一下. 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=55; 4 5 int g[12]={10,9,6,5,12,3,11,14,7,13,15}; 6 int f[maxn*maxn]

HDU 5441 Travel 并查集

HDU 5441 Travel 题意:一张无向图,q个查询,对于每个x,有多少对点之间的路径中最长的一条路不大于x. 思路:比赛时王秋平写的,我补下题.这题也比较简单,将边排序,从小到大加到并查集,对查询也排序,从小到大对于每个查询把不大于x的边加到并查集,用cnt[y]记录以y为根的连通块有多少节点,那么在连通块发生 变化时,ans=2 * cnt[x] * cnt[y] 1 #include <iostream> 2 #include <cstdio> 3 #include &

HDU 2818 (矢量并查集)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2818 题目大意:每次指定一块砖头,移动砖头所在堆到另一堆.查询指定砖头下面有几块砖头. 解题思路: [HDU数据有问题],数据从0开始,且给定n块砖头(比如1000),数据会有第1005块砖头,导致访问越界. [解决方案],并查集初始化范围改为0~maxn(30005) 由于只给定一块砖头,却要移动所在堆.所以需要并查集维护所在堆. p[x]=y,即x所在堆的堆底是y,注意此时并查集是有方向的.

hdu 3081(二分+并查集+最大流||二分图匹配)

Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3558    Accepted Submission(s): 1158 Problem Description Presumably, you all have known the question of stable marriage match. A