《博弈 - 整理》

green博弈:

模型:对于一棵树,两个人A和B每次可以选定一个点删去,同时这个点的子树也会被删去。

考虑必胜态和必败态的判断。

首先如果是一条链,那么就可以看成取一堆石子。

那么,从根上再延伸出一条链,那么就可以看成取两堆石子,那么就是标准的NIM博弈。

我们知道NIM博弈的答案就是SG函数值,也就是多个堆的异或和。

那么这里我们就可以推出根的SG函数值就是它的子树的SG函数的异或和。

 也由上面推导可见,我们根的SG函数和自身没关系,所以对于每个节点的SG函数,初始值应该为0。

在处理子树的时候,再和每个子树加上1。

 

https://ac.nowcoder.com/acm/contest/16832/J

《博弈 - 整理》
// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const int N = 1e6 + 5;
const int M = 1e5 + 5;
const LL Mod = 1e9 + 7;
#define pi acos(-1)
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
namespace FASTIO{
    inline LL read(){
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
}
using namespace FASTIO;

vector<int> G[N];
int sg[N];
void dfs(int u,int fa) {
    sg[u] = 0;
    for(auto v : G[u]) {
        if(v == fa) continue;
        dfs(v,u);
        sg[u] ^= (sg[v] + 1);
    }
}
int main() {
    int ca;ca = read();
    while(ca--) {
        int n;n = read();
        for(int i = 1;i <= n;++i) G[i].clear();
        for(int i = 1;i < n;++i) {
            int x,y;x = read(),y = read();
            G[x].push_back(y);
            G[y].push_back(x);
        }
        dfs(1,0);
        printf("%s\n",sg[1] ? "NO" : "YES");
    }

   //  system("pause");
    return 0;
}
View Code

 

上一篇:【python自动化办公】电脑全盘路径/指定路径下文件(夹)查找,并封装为可执行程序


下一篇:算法学习————SG函数和SG定理