HDU暑假多校第六场K-werewolf

一、题意

好人必然说真话,坏人不一定说真话,给定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 = 1000233;

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] = 1;
    if(vis[tar] == 1 && isW == 1)
    {
        wolfpoint = tar;
        is_after_wolfpoint = 0;
        isWolf[now] = 0;
        vis[now] = 0;
        return false;
    }
    if(isWolf[tar] == 1 && isW ==0)
    {
        isWolf[now] = 1;
        is_after_wolfpoint =1;
        wolfpoint = tar;
        vis[now] = 0;
        return false;
    }
    if(vis[tar] == 0 && isW == 0)
    {
        bool succ = dfs(tar);
        if(succ){
            isWolf[now] = 0;
            vis[now] = 0;
            return true;
        }else{
            if(now == wolfpoint)is_after_wolfpoint = true;
            if(is_after_wolfpoint)isWolf[now] = 1;
            else isWolf[now] = 0;
            vis[now] = 0;
            return false;
        }
    }
    vis[now] = 0;
    isWolf[now] = 0;
    return true;
}

void push_up(int now)
{
    isWolf[now] = 1;
    int len = Gb[now].size();
    for(int i=0;i<len;++i)
    {
        int tar = Gb[now][i].first;
        int isW = Gb[now][i].second;
        if(isW ==0)push_up(tar);
    }
}

void init()
{
    cin>>n;
    memset(isWolf,-1,sizeof(isWolf));
    for(int i=0;i<=n+23;++i)Gb[i].clear();
    for(int i=1;i<=n;++i)
    {
        int tar ;
        char str[23];
        cin>>tar>>str;
        int isW = str[0] == 'w'?1:0;
        Ga[i] = make_pair(tar,isW);
        Gb[tar].push_back(make_pair(i,isW));
    }
    int cntt = 0;
    for(int i=1;i<=n;++i)
    {
        if(isWolf[i] == 1)cntt++;
        if(isWolf[i] != -1)continue;
        dfs(i);            
        if(isWolf[i] == 1)cntt++,push_up(i); 
    }
    cout<<0<<" "<<cntt<<endl;

}



int main()
{
    cin.sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)init();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/rikka/p/9448913.html