一、题意

好人必然说真话,坏人不一定说真话,给定N个人的言论<每人一个发言、不谈及自己>,要求指出有多少个人一定是好人,有多少个人一定是坏人。
#define 狼人 坏人
#define 村民 好人

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.

二、思路

假设某个局面,我们设定了N个好人及其言论,同时言论不相互矛盾——没有一个好人说谎,则同时将他们换成坏人时局面不存在相互矛盾的地方。

于是可以认为,我们无法判定谁一定是好人。但是反过来,我们可以判定一个人一定是坏人——即当他当不成好人的时候他就一定是坏人。

则可以使用"假设一个人是好人,并采信他的一切言论,如果出现矛盾则认为他言论不实,否则认为他可以成为好人"的方式进行判定。

考虑搜索时的剪枝:

1、应当将每个判定为坏人的人做特殊处理:所有指认坏人为好人的人,都是坏人。并递归的向上处理所有指认坏人为好人的人。

2、考虑每次搜索,都将有两个结果:成矛盾环或者合法:
  a、若成矛盾环,则矛盾点及以上的所有点都一定是坏人;环内除了矛盾点外所有节点为好人
  b、若合法,则链路上每个人都是好人。

#include<bits/stdc++.h>
using namespace std; #define ll long long
#define pp pair<int,int>
#define vecp vector<pp>
const int MAXN = ; pp Ga[MAXN];
vecp Gb[MAXN];
int isWolf[MAXN];
int n; int wolfpoint;
bool is_after_wolfpoint; int vis[MAXN]; bool dfs(int now)
{ // cout<<"check_dfs: "<<now<<endl;
int tar = Ga[now].first;
int isW = Ga[now].second;
vis[now] = ;
if(vis[tar] == && isW == )
{
wolfpoint = tar;
is_after_wolfpoint = ;
isWolf[now] = ;
vis[now] = ;
return false;
}
if(isWolf[tar] == && isW ==)
{
isWolf[now] = ;
is_after_wolfpoint =;
wolfpoint = tar;
vis[now] = ;
return false;
}
if(vis[tar] == && isW == )
{
bool succ = dfs(tar);
if(succ){
isWolf[now] = ;
vis[now] = ;
return true;
}else{
if(now == wolfpoint)is_after_wolfpoint = true;
if(is_after_wolfpoint)isWolf[now] = ;
else isWolf[now] = ;
vis[now] = ;
return false;
}
}
vis[now] = ;
isWolf[now] = ;
return true;
} void push_up(int now)
{
isWolf[now] = ;
int len = Gb[now].size();
for(int i=;i<len;++i)
{
int tar = Gb[now][i].first;
int isW = Gb[now][i].second;
if(isW ==)push_up(tar);
}
} void init()
{
cin>>n;
memset(isWolf,-,sizeof(isWolf));
for(int i=;i<=n+;++i)Gb[i].clear();
for(int i=;i<=n;++i)
{
int tar ;
char str[];
cin>>tar>>str;
int isW = str[] == 'w'?:;
Ga[i] = make_pair(tar,isW);
Gb[tar].push_back(make_pair(i,isW));
}
int cntt = ;
for(int i=;i<=n;++i)
{
if(isWolf[i] == )cntt++;
if(isWolf[i] != -)continue;
dfs(i);
if(isWolf[i] == )cntt++,push_up(i);
}
cout<<<<" "<<cntt<<endl; } int main()
{
cin.sync_with_stdio(false);
int t;
cin>>t;
while(t--)init();
return ;
}

HDU暑假多校第六场K-werewolf的更多相关文章

  1. HDU暑假多校第八场G-Card Game

    一.题意 给出N个卡牌,卡牌的正反两面具有两个数字,取值范围为[1,2*n],给出若干个默认正面向上的卡牌,求最小反转多少张卡牌可以使得,每张卡牌朝上的面上都有一个不同的数字,同时满足最小反转次数的反 ...

  2. HDU暑假多校第八场J-Taotao Picks Apples

    一.题意 给定一个序列,之后给出若干个修改,修改的内容为在原序列的基础上,将某一位元素的值改成给定的值<每次修改相互独立,不保存修改后的结果>.之后询问,在选择第一位元素的情况下,最长递增 ...

  3. 牛客暑假多校第六场I-Team Rocket

    一.题意 我们是穿越银河的火箭队....... 给出若干个区间,之后给出若干个点,要求对每个点求出,第一个覆盖点的区间的数量,之后用当前所有点覆盖的区间的序号的乘积结合输入的Y来生成下一位点.最后输出 ...

  4. HDU暑假多校第三场H.Monster Hunter

    一.题意 给定一个树状地图,每个树节点上有一只怪物,打死一只怪物的过程中将会消耗A点HP,打死之后将会获得B点HP.因为树状结构,所以每只怪物必须先打死父节点的怪兽之后在打死子节点的怪物.现在,给定每 ...

  5. HDU暑假多校第四场J-Let Sudoku Rotate

    一.题意 Sudoku is a logic-based, combinatorial number-placement puzzle, which is popular around the wor ...

  6. 牛客暑假多校第六场 I Team Rocket

    题意: 现在有n条火车, 每条火车都有一个运行 [ Li, Ri ], 现在有m支火箭队, 每次火箭队都会破坏这整条铁路上的一个点, 如果一条火车的运行区间[Li, Ri] 被破坏了, 那么这条火车会 ...

  7. 2020牛客多校第八场K题

    __int128(例题:2020牛客多校第八场K题) 题意: 有n道菜,第i道菜的利润为\(a_i\),且有\(b_i\)盘.你要按照下列要求给顾客上菜. 1.每位顾客至少有一道菜 2.给顾客上菜时, ...

  8. 2014多校第六场 1010 || HDU 4930 Fighting the Landlords (模拟)

    题目链接 题意 : 玩斗地主,出一把,只要你这一把对方要不了或者你出这一把之后手里没牌了就算你赢. 思路 : 一开始看了第一段以为要出很多次,实际上只问了第一次你能不能赢或者能不能把牌出尽. #inc ...

  9. 【HDU】4923 Room and Moor(2014多校第六场1003)

    Room and Moor Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) ...

随机推荐

  1. 使用Cloud application Studio在C4C UI里创建下拉列表(dropdown list)

    在Cloud Application Studio里新建一个Code List Data Type: 维护Value和描述信息,以及在ABSL里使用的constant值. 保存之后,上述维护的信息会存 ...

  2. apache 配置跨域访问

    在httpd.conf找到  去掉# LoadModule headers_module modules/mod_headers.so 然后在 独立域名配置 加入 Header set Access- ...

  3. 【luogu P1972 [SDOI2009]HH的项链】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1972 真是不懂为什么要卡莫队! #include <cmath> #include <cs ...

  4. Android学习笔记_35_PopupWindow泡泡窗口的实现及GridView应用

    1.PopupWindow是一个可以显示在当前Activity之上的浮动容器,PopupWindow弹出的位置是能够改变的,按照有无偏移量,可以分为无偏移和有便宜两种:按照参照对象的不同又可以分为两种 ...

  5. Android学习笔记_4_单元测试

    在实际开发中,开发android软件的过程需要不断地进行测试.而使用Junit测试框架,侧是正规Android开发的必用技术,在Junit中可以得到组件,可以模拟发送事件和检测程序处理的正确性. 1. ...

  6. SQL批量添加,更新,删除

    SQL语句: 存储过程: 代码: 这里说的是关于SQL的批量操作数据. 需要准备: 三层框架:利用 动软代码生成器(可以快速生成增删改查) 生成三层 Model,BLL,Dal ①DbHelpeSQL ...

  7. eclipse的中文插件链接及使用方法

    链接:http://www.eclipse.org/babel/downloads.php 帮助-->安装-->打开链接使用链接里面的语言包下载地址-->下载安装-->完成

  8. Navicat for Mysql修改MySQL数据库密码,图文详解

    1.创建一个连接 2.打开连接 3.按照图示123依次点击 4.输入新密码 5.查看实现修改密码功能的SQL语句(此步骤非必须) 6.最关键的一步:点击保存 7.出现如下现象,恭喜你,修改密码成功! ...

  9. java连接Redis初始化jedis失败!

    Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstant ...

  10. mysql-新增表前判断同名表是否存在

    新增多个表时,如果有同名表会报错,导致其中一个表不能正确创建,此时可以用以下语句进行判断: DROP TABLE IF EXISTS USER; --判断表是否存在,如果存在就删除! CREATE T ...