• 有根数博弈


    题目链接

    有一个棋子放在一颗有根树的根上。你和算卦先生轮流把这个棋子向所在点的其中一个儿子移动(只能移动到儿子)。不能再移动就算失败(即棋子所在节点没有儿子)。
    算卦先生来问你,如果你先手,你是否有必胜策略

    分析:用DFS,从根到尾一点点来,因为会沿着一条路径走到黑,每个点只会被访问到一次,大致是O(N)级的复杂度;

    用pre来标记父节点免得上下来回走,如果有节点可走,就继续往下走,没节点可走时返回f。

    或者是该节点的所有儿子节点都是叶子(这种情况下它们都会返回TRUE),也会返回f

    一层层往上推进,在最上面一层,只要有一个节点是必赢节点,选择这个节点,即可赢(因为只要所有儿子节点都是True,返回值才会为负)

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int inf=1<<30;
     4 typedef long long ll;
     5 const double pi=acos(-1);
     6 const int mod=1e9+7;
     7 const int maxn=1e4+7;
     8 vector<int> v[maxn];
     9 //dfs函数每层返回的是在这一层下棋的人是输还是赢 
    10 bool dfs(int s,int pre){//pre函数记录它是从哪层来的,免得父到子,子又到父 
    11     for(int i=0;i<v[s].size();i++){
    12         int a=v[s][i];
    13         if(a==pre) continue;
    14         if(!dfs(a,s)) return true;//下一层走不了了,那这一层就是最后一层,在这一层执棋的人就赢 
    15     }
    16     return false;//所有边都遍历完了仍没找到可赢的情况,说明这一层无法走,返回FALSE 
    17 }
    18 int main(){
    19     int T;scanf("%d",&T);
    20     while(T--){
    21         int n,r;scanf("%d%d",&n,&r);
    22         for(int i=1;i<=n;i++) v[i].clear();
    23         for(int i=1;i<n;i++){
    24             int x,y;scanf("%d%d",&x,&y);
    25             v[x].push_back(y);
    26             v[y].push_back(x);
    27         }
    28         if(dfs(r,-1)) cout<<"Gen
    ";
    29         else cout<<"Dui
    ";
    30     }
    31     return 0;
    32 }
  • 相关阅读:
    Educational Codeforces Round 72 (Rated for Div. 2)
    2249: Altruistic Amphibians 01背包
    lh的简单图论
    E. XOR Guessing 交互题 Educational Codeforces Round 71 (Rated for Div. 2)
    C. Helga Hufflepuff's Cup 树形dp 难
    B. Marvolo Gaunt's Ring 前缀后缀
    android学习-IPC机制之ACtivity绑定Service通信
    大数组分时加载算法 timedChunk
    log4j 配置和使用
    fastjson 配置和使用
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/10424516.html
Copyright © 2020-2023  润新知