题意:

给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1。 在一局游戏开始时,会确定一个节点作为根。接下来从女生开始,双方轮流进行 操作。
当一方操作时,他们需要先选择一个不为根的点,满足该点到其父亲的边权为1; 然后找出这个点到根节点的简单路径,将路径上所有边的权值翻转(即0变成1,1 变成0 )。
当一方无法操作时(即所有边的边权均为0),另一方就获得了胜利。
如果在双方均采用最优策略的情况下,女生会获胜,则输出“Girls win!”,否则输 出“Boys win!”。
为了让游戏更有趣味性,在每局之间可能会有修改边权的操作,而且每局游戏指 定的根节点也可能是不同的。
具体来说,修改边权和进行游戏的操作一共有m个,具体如下:
∙∙“0 x”表示询问对于当前的树,如果以x为根节点开始游戏,哪方会获得胜利。
∙∙“1 x y z ”表示将x和y之间的边的边权修改为z。

分析:

一道在树上的博弈论题

首先,我们先不管是否是最优策略,我们先就愣头青走憨憨走法——每次都走最深的这样一个节点,比如

那么我们按照这个规则,先看左边那条链并先选7号节点

对了,这里其实还有一个小小的性质,每条链末尾的0一定是没用的,因为只有他后面的1才能使它翻转成1,而他是末尾的0

所以知道这个性质以及选完7号节点后,树就变成了这样子

然后就是5号节点

最后是4号节点

你会发现,假如只有这条链的话到这里已经决出胜负了

而且不难发现的是,在这种憨憨决策中,与根节点直接相连的那条边似乎非常的重要

因为假如我们将这条链划分一下肯定是一块全是1的链,一块全是0的链相间分布(显然)

那么我们这种憨憨走法第一步会将最后一块1的链吞掉,然后剩下的链翻转,你也可以理解为规则翻转,也就是说我们下次就要选0的那块了

以此类推,那么如果最后一块是1的话也就是说连接根节点的那条边是1,那么你就会走奇数步,而如果是0的话就会走偶数步

奇数步与偶数步也就对应了游戏的输赢(奇数对应女孩赢,偶数对应男孩赢)

当然,这种憨憨走法男主和女主显然不会这么走

比如

在憨憨走法的前提下,这显然是个男孩必赢的局,那女孩有什么能做的,她可不想输啊!

走5必输,那就走4吧

你会发现,之前的走法会让链的块数减一,而这次却让链的块数加一,但这时如果两人继续“憨憨”的话依然是男孩必赢,因为这次相当于男孩先手,而这次有奇数个块,显然男孩必赢

那么我们不难发现,如果我们即使突然“醒悟”,不憨了,但也难逃输的命运,而已经命中注定赢的那位,只需要一直憨下去就行了,当然他也可以皮一下,但就是输不了就很气

当然一条链是这样,更多的链显然也一定是这样,因为每条链都是“命中注定”,那么我们就可以把一颗树化简成一个根节点连着一些节点

因为每条链的结果只与他与根节点连接的那条边有关

原来一条复杂的树,现在只剩下一个“拖把头”,显然就很好做了,轮流取1就完事了,那么很容易得到,最后“拖把头”里1的个数是奇数就是女孩赢,偶数个就是男孩赢

最后就是这个题目中的修改操作以及换根查询了,修改我直接采用莽着改,的确有超时的风险,不过这题核心是想到这个转化,我觉得做数据的应该是做人的qaq

查询当然也是扫一遍他连着的所有边,具体如何实现,我相信你们都写的出来):

代码:

#include<cstdio> #include<algorithm> #include<vector> using namespace std; const int maxn=4e4+1; struct Node { int pos,val; Node(){} Node(int POS,int VAL){pos=POS,val=VAL;} }; vector<Node> e[maxn]; int main() { int t,n,m,x,y,z,p; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)e[i].clear(); for(int i=1;i<n;i++) { scanf("%d%d%d",&x,&y,&z); e[x].push_back(Node(y,z)); e[y].push_back(Node(x,z)); } while(m--) { scanf("%d",&p); if(!p) { scanf("%d",&x); int ans=0; for(int i=0;i<e[x].size();i++) ans+=e[x][i].val; if(ans&1) printf("Girls win!\n"); else printf("Boys win!\n"); } else { scanf("%d%d%d",&x,&y,&z); for(int i=0;i<e[x].size();i++) { if(y==e[x][i].pos) { e[x][i].val=z; break; } } for(int i=0;i<e[y].size();i++) { if(x==e[y][i].pos) { e[y][i].val=z; break; } } } } } return 0; }

说实话我还真不知道咋展示代码[笑哭]

其实实现过程就是把每个节点连接的节点都用vector存一下,然后每次修改的时候就扫一遍,找到你想修改的那个点对应连的边,然后改就完事了

题目分享P的更多相关文章

  1. 2019年腾讯PHP程序员面试题目分享

    有需要学习交流的友人请加入交流群的咱们一起,有问题一起交流,一起进步!前提是你是学技术的.感谢阅读! 点此加入该群​jq.qq.com 1. php 的垃圾回收机制 PHP 可以自动进行内存管理,清除 ...

  2. 20190924-LeetCode解数独题目分享

    解决数独 题目描述 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一个以 ...

  3. 题目分享E 二代目

    题意:一棵点数为n的树,每个节点有点权,要求在树中中找到一个最小的x,使得存在一个点满足max(该点点权,该点相邻的点的点权+1,其他点的点权+2)=x 分析:首先要能把题目转化为上述题意 首先题目让 ...

  4. 题目分享D 二代目

    题意:给定一个T条边的无向图,求S到E恰好经过N条边的最短路径 T≤100 N≤1000000 分析:(据说好像假期学长讲过) 首先很容易想到的是dp[i][j][k]表示从i到j经过k条边的最短路径 ...

  5. 题目分享C 二代目

    题意:一个数列是由 1 1 2 1 2 3 1 2 3 4 1 2 3 4 5 1 2 3 4 5 6.....组成,也就是1-1,1-2,1-3......并且如果遇到多位数也要拆成数字比如1-10 ...

  6. 题目分享X

    题意:一张票有n位数,如果这张票的前一半数字的和等于后一半数字的和(n一定是偶数),就称这张票为快乐票.有些数被擦除了,标记为’?’(’?‘的个数也是偶数),现在Monocarp 和 Bicarp 进 ...

  7. 题目分享V

    题意:现在两个人做游戏,每个人刚开始都是数字1,谁赢了就能乘以k^2,输的乘以k(k可以是任意整数,每次不一定相同)现在给你最终这两个人的得分,让你判断是否有这个可能,有可能的话Yes,否则No. 分 ...

  8. 题目分享T

    题意:蛐蛐国里现在共有n只蚯蚓(n为正整数).每只蚯蚓拥有长度,我们设第i只蚯蚓的长度为a_i(i=1,2,...,n),并保证所有的长度都是非负整数(即:可 能存在长度为0的蚯蚓).每一秒,神刀手会 ...

  9. 题目分享H 二代目

    题意:有m个限制,每个限制l1,r1,l2,r2四个数,限制了一个长度为n的数第l1到r1位要与第l2到r2相同,保证r1-l1=r2-l2,求在限制下一共有多少种数 分析: 暴力的话肯定是从l1-r ...

随机推荐

  1. 推荐一款超实用的GitHub可视化代码树插件:Octotree

    前言 大家在GitHub查看代码的时候,是不是会经常跳转搜索代码!过一段时间就不知道自己跑到哪里了!有了这款工具,妈妈再也不用担心我找不到代码位置了! 直接上效果图 插件名称 : octotree 作 ...

  2. python3(二十) module

    # 在Python中,一个.py文件就称之为一个模块(Module) # 1.最大的好处是大大提高了代码的可维护性. # 2.可以被其他地方引用 # 3.python内置的模块和来自第三方的模块 # ...

  3. ${param.pageNo}是什么意思?

    1.${param.id}与request.getParameter("id"):功能相同2.param.id获取输入的参数id,也可理解为的是form或者div表单里的ID. r ...

  4. 使用SVGDeveloper画svg地图详细过程

    使用步骤 1.  安装svg 2.  具体操作 1.     打开svg,点击file ,new,默认svg,点击ok 显示界面如下: 然后点击image 把鼠标放到代码下面的的桌面上,鼠标箭头会变成 ...

  5. Personal Photo Management Application

    Customer Problems & Needs People may take a large number of photos and their phone don't have en ...

  6. 食物链 POJ - 1182 (并查集的两种写法)

    这是一个非常经典的带权并查集,有两种写法. 1 边权并查集 规定一下,当x和y这条边的权值为0时,表示x和y是同类,当为1时,表示x吃y,当为2时,表示x被y吃. 一共有三种状态,如图,当A吃B,B吃 ...

  7. .NET中 kafka消息队列、环境搭建与使用

    前面几篇文章中讲了一些关于消息队列的知识,就每中消息队列中间件,我们并没有做详细的讲解,那么,今天我们就来详细的讲解一下消息队列之一kafka的一些基本的使用与操作. 一.kafka介绍 kafka: ...

  8. eclipse添加方法注释

    打开注释模板编辑窗口:Window ->Preferences->java -> Code Style -> Code Template->Comments type 设 ...

  9. Python爬虫---爬取腾讯动漫全站漫画

    目录 操作环境 网页分析 明确目标 提取漫画地址 提取漫画章节地址 提取漫画图片 编写代码 导入需要的模块 获取漫画地址 提取漫画的内容页 提取章节名 获取漫画源网页代码 下载漫画图片 下载结果 完整 ...

  10. C语言字符数组超细讲解

    看到标题,有不少朋友会想:字符数组不也是数组吗?为什么要单独拿出来讲哩?莫非它是朵奇葩? 哈哈,确实,一起来认识一下这朵数组界的奇葩吧! 一.字符数组的定义.引用.初始化 大家好!我是字符数组,看我的 ...