[NIM博弈]矿物运输
Posted yuxiaoze
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[NIM博弈]矿物运输相关的知识,希望对你有一定的参考价值。
题目限制
1500 ms 128 M
题目描述
在某个不知名的行星上蕴含着大量冰晶矿,Jim和他的好兄弟Swan自然不能放过这个赚钱的好机
会。Jim在整个星球上开掘树型矿洞,每个矿坑之间都有矿道相连。Jim和Swan在每个矿坑开采了
大量的矿石,现在他们面临一个新的问题,怎么把所有的矿石运出去。
已知,矿坑与矿坑之间形成了有向的树形结构,即除0号矿坑以外每个矿坑都有与其相连的父亲矿
坑。Jim总共开采了 n个矿坑并将其从0到 n-1 编号 ,每个矿坑都存有 val[i]个单位的矿石。
Jim和Swan每次操作都可以从某个矿坑移动至少1个单位的矿石到其父亲矿坑。Jim和Swan决定比
试一下,由Jim开始轮流操作,最后不能操作的人输。Jim偷偷的找到了你,他想知道在两人都采取
最优策略的情况下是否Jim能够赢得这场比试。
输入格式
多组数据
第一行为数据组数,T <=30
第二行一个整数n,表示矿坑数目,n<=2e5
接下来一行为n-1个整数fa[1]..fa[n-1],分别描述了除根节点外每个点的父亲。方便起见,保证
0<=fa[i]<i。
接下来一行为n个非负整数val[0]..val[n-1],分别描述了每个矿坑初始的矿石数。0<=val[i]<1e9。
输出格式
对于每组数据,输出一行,若Jim必胜则输出"win",否则输出"lose"(不含引号)。
数据范围
对于 25%的数据 保证 n<=10
对于 50%的数据 保证 n<=1000
存在 10%的数据 每个矿坑只有一个子矿坑
存在 10%的数据 除0号矿坑外,每个矿坑都与0号矿坑相连。
对于 100%的数据 保证 n<=200000
输入样例
1
6
0 0 2 2 4
1 4 0 1 1 2
输出样例
win
NIM博弈讲解 https://www.luogu.org/problemnew/solution/P2197
https://www.iteye.com/blog/huobengle-1386808
多个有向图(G)游戏的
和SG函数值等于它包含的各个子游戏SG函数值的异或和,即SG(G) = SG(G1) xor SG(G2) xor …
SG(Gm)。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int N=200005; 5 int n,fa[N],val[N],sum; 6 int num,last[N],nxt[N],ver[N]; 7 inline void add(int x,int y) {nxt[++num]=last[x]; last[x]=num; ver[num]=y;} 8 void dfs(int x,int dep) 9 {if(dep&1) sum^=val[x]; 10 for(int i=last[x];i;i=nxt[i]) 11 {int y=ver[i]; 12 dfs(y,dep+1); 13 } 14 } 15 int main() 16 { 17 freopen("ore.in","r",stdin); 18 freopen("ore.out","w",stdout); 19 int t; scanf("%d",&t); 20 21 while(t--) 22 {scanf("%d",&n); 23 num=sum=0; memset(last,0,sizeof(last)); 24 25 for(int i=2;i<=n;i++) 26 {scanf("%d",&fa[i]); fa[i]++; add(fa[i],i); } 27 for(int i=1;i<=n;i++) scanf("%d",&val[i]); 28 dfs(1,0); 29 if(sum) printf("win "); 30 else printf("lose "); 31 } 32 33 34 return 0; 35 }
以上是关于[NIM博弈]矿物运输的主要内容,如果未能解决你的问题,请参考以下文章