最简单的博弈论——HDU - 5963 朋友 (博弈)
Posted dzn2004
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最简单的博弈论——HDU - 5963 朋友 (博弈)相关的知识,希望对你有一定的参考价值。
OK,好的先看一下题意:
B君在围观一群男生和一群女生玩游戏,具体来说游戏是这样的:
给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1。 在一局游戏开始时,会确定一个节点作为根。接下来从女生开始,双方轮流进行 操作。
当一方操作时,他们需要先选择一个不为根的点,满足该点到其父亲的边权为1; 然后找出这个点到根节点的简单路径,将路径上所有边的权值翻转(即0变成1,1 变成0 )。
当一方无法操作时(即所有边的边权均为0),另一方就获得了胜利。
如果在双方均采用最优策略的情况下,女生会获胜,则输出“Girls win!”,否则输 出“Boys win!”。
为了让游戏更有趣味性,在每局之间可能会有修改边权的操作,而且每局游戏指 定的根节点也可能是不同的。
具体来说,修改边权和进行游戏的操作一共有m个,具体如下:
??“0 x”表示询问对于当前的树,如果以x为根节点开始游戏,哪方会获得胜利。
??“1 x y z ”表示将x和y之间的边的边权修改为z。
—————————————————————————————————————————————————————————————————————————————
sorry,代码在下面
题意应该比较好懂,一般人应该也知道这是博弈论。
但是我建议大家先模拟一下样例,方便理解。
但是具体怎么想呢?
博弈论一般都要先想什么时候是必胜状态。
同理:
这道题的必胜状态是什么呢?
当根节点所连的边中只有一条边的权值为1的话,那么肯定是 女生赢。
当根节点只连一条边,且边的权值是1,在这条边之后又连了很多条边,随便编的权值。
第一次女生翻转,那么第一条边的权值变成了0. 男生肯定不能翻转第一条边,
如果男生不能翻转,那么女生就赢了,如果男生还可以翻转,这时候第一条边又变成了1.
女生翻转又把第一条边变成了0.所以男生永远不可能翻转第一条边。
所以这种状态一定是女生赢。(根节点连了一条权值为1 的边。)
如果根节点连的边的权值和 为奇数,就是女生赢,反之就是男生赢。
是不是很简单。
然后是超级简单的代码。
提醒大家注意理解sum数组的含义。
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 const int maxn=40005; 5 struct node{ 6 int from,to,next,value; 7 }e[maxn<<1]; 8 int head[maxn],cnt,sum[maxn]; 9 void add(int x,int y,int z){ 10 e[++cnt].from=x;e[cnt].to=y;e[cnt].value=z;e[cnt].next=head[x];head[x]=cnt; 11 } 12 int main(){ 13 //freopen("a.in","r",stdin); 14 int t;scanf("%d",&t); 15 while(t--){ 16 memset(e,0,sizeof(e)); 17 memset(head,0,sizeof(head)); 18 memset(sum,0,sizeof(sum)); 19 cnt=0; 20 int n,m;scanf("%d%d",&n,&m); 21 for(int i=1;i<n;i++){ 22 int x,y,z;scanf("%d%d%d",&x,&y,&z); 23 add(x,y,z);add(y,x,z); 24 sum[x]+=z;sum[y]+=z; 25 } 26 for(int i=1;i<=m;i++){ 27 int u;scanf("%d",&u); 28 if(u==0){ 29 int x;scanf("%d",&x); 30 int ans=sum[x]; 31 if(ans%2==1)printf("Girls win! "); 32 else printf("Boys win! "); 33 } 34 else { 35 int x,y,z;scanf("%d%d%d",&x,&y,&z); 36 for(int k=head[x];k;k=e[k].next){ 37 int v=e[k].to; 38 if(v==y){ 39 sum[x]-=e[k].value; 40 sum[x]+=z; 41 e[k].value=z; 42 } 43 } 44 for(int k=head[y];k;k=e[k].next){ 45 int v=e[k].to; 46 if(v==x){ 47 sum[y]-=e[k].value; 48 sum[y]+=z; 49 e[k].value=z;break; 50 } 51 } 52 } 53 } 54 } 55 return 0; 56 }
以上是关于最简单的博弈论——HDU - 5963 朋友 (博弈)的主要内容,如果未能解决你的问题,请参考以下文章