[codeforces] Gym - 101246D Fire in the Country (BFS + 基础博弈)

4 篇文章 0 订阅
3 篇文章 0 订阅

[codeforces] Gym - 101246D Fire in the Country (BFS + 基础博弈)

题目链接: D. Fire in the Country
题目大意:
给定 n 个点,m条边, 有一个机器人, 初始在一个号点, 两个人轮流操作, 每次可以让机器人走到一个相邻的点, 大火从一号点开始蔓延, 每次所有着火点相连的点都会被点着, 问最终谁让机器人走到着火点谁就输。

解题思路: 题意有点绕, 我们简化一下, 就是两个人轮流控制一个机器人走,从一号点, 不能往回走(因为后面的点走完之后就会着火), 那么谁站在叶子节点谁就输了。
举例子: 就1,2两个点, A让机器人从1走到2, 轮到B的时候, B走不动了, 然后大火会蔓延到2, 那么B就输了。(不理解的话自己随便画一个树推一下) 所以说, 叶子节点是必败点。
这时候需要知道博弈那基本的两句话:
一个点是必胜点当且仅当至少有一个后继点是必败点
一个点是必败点当且仅当所有的后继状态都是必胜点
所以只要跑一遍BFS, 之后从后往前推, 就可以知道每一个点是必胜还是必败了。

注意点: 用一个需要注意的是有可能会有同层的边, 这条边是没有用的边, 只有dis比当前点深的点才是他的后继点。

/**********************************************
 *Author*        :ZZZZone
 *reated Time*  : 2017/8/7 21:00:51
 *ended  Time*  : 2017/8/7 21:13:27
*********************************************/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;
typedef unsigned long long ULL;
const int MaxN = 1000;
vector<int> edge[MaxN + 5];
int q[MaxN + 5], dis[MaxN + 5];
bool f[MaxN + 5];
int n, m;

void bfs(){
    int head = 1, tial = 0; dis[1] = 1;
    q[++tial] = 1;
    while(head <= tial){
        int u = q[head];
        for(int i = 0; i < edge[u].size(); i++){
            int v = edge[u][i];
            if(!dis[v]){
                dis[v] = dis[u] + 1;
                q[++tial] = v;
            }
        }
        head++;
    }
    for(int i = tial; i >= 1; i--){
        int u = q[i];
        for(int j = 0; j < edge[u].size(); j++){
            int v = edge[u][j];
            if(dis[v] > dis[u] && ! f[v]) f[u] = true;
        }
    }
}

int main()
{
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    while(~scanf("%d %d", &n, &m)){
        for(int i = 1; i <= m; i++){
            int u, v;
            scanf("%d %d", &u, &v);
            edge[u].push_back(v);
            edge[v].push_back(u);
        }
        bfs();
        if(f[1]) printf("Vladimir\n");
        else printf("Nikolay\n");
        memset(f, 0, sizeof(f));
        memset(dis, -1, sizeof(dis));
        memset(edge, 0, sizeof(edge));
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值