zoukankan      html  css  js  c++  java
  • 有根数博弈

    题目链接

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

    分析:用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 }
  • 相关阅读:
    learnyou 相关网站
    hdu 3038 How Many Answers Are Wrong
    hdu 3047 Zjnu Stadium 并查集高级应用
    poj 1703 Find them, Catch them
    poj 1182 食物链 (带关系的并查集)
    hdu 1233 还是畅通工程
    hdu 1325 Is It A Tree?
    hdu 1856 More is better
    hdu 1272 小希的迷宫
    POJ – 2524 Ubiquitous Religions
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/10424516.html
Copyright © 2011-2022 走看看