正题

题目链接:https://www.luogu.com.cn/problem/P7443?contestId=41429


题目大意

\(n\)个点的一棵有根树,两个人从一号点开始进行有向图博弈。

告诉你Alice是先手还是后手,然后你可以选择加一条链接\((u,v)\)的有向边,权值为\(A\times a_u+B\times a_v\)。求最小权值使得第一个人获胜。(如果死循环则无法获胜)

\(1\leq T\leq 2\times 10^3,2\leq n\leq 2\times 10^5,\sum n\leq 5\times 10^6,1\leq a_i,A,B\leq 10^9\)


解题思路

先考虑没有加边情况的胜负。定义\(1\)为先手必败状态,那么所有叶子都是\(1\)。然后每个节点是所有子节点的或值再异或\(1\)。

那么如果已经必胜就是\(0\)了,否则我们需要改变一号节点的状态。

先考虑加一条返祖边的影响,首先这条边肯定是加在Alice行动的节点上,否则Bob可以选择不走。

而且\(v\)肯定得是先手必败的局面,否则没有意义。然后如果\(v\)是先手必败的话,那么Bob显然还是可以往之前的路径走,如果走到\(u\)节点时是Alice移动那么状态不会改变,否则Bob可以继续走返祖边造成死循环。所以返祖边不能影响状态。

然后考虑翻转一个点的状态需要做什么。

如果这个点是先手必败,那么我们只需要找到另一个先手必败的节点连接过去或者翻转子节点的状态就可以翻转该节点的状态。

如果这个点是先手必胜,那么如果子节点中有两个或以上的先手必败那么该节点无法翻转,否则翻转那个先手必败的节点即可。

那么现在我们需要解决寻找除了该节点到根的路径上的点中权值最小的先手必败节点权值。

用优先队列的话会\(TLE\),所以我们考虑其他方法,我们对于每个节点记录一下子树中最大的先手必败节点权值,然后每次向下递归的时候就取所有除了递归子树以外的子节点子树丢进最小值就好了。

这个记录一个次大值和最大值就可以实现。

时间复杂度\(O(\sum n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<queue>
#define ll long long
using namespace std;
const ll N=2e5+10;
struct node{
ll to,next;
}a[N];
ll T,n,m,t,A,B,tot,w[N],fa[N],z[N];
ll ls[N],f[N],s[N],ans;
ll read(){
ll x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
void addl(ll x,ll y){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;return;
}
void dfs(ll x){
f[x]=s[x]=0;z[x]=1e9+7;
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
dfs(y);f[x]|=f[y];s[x]+=f[y];
z[x]=min(z[x],z[y]);
}
f[x]^=1;
if(f[x])z[x]=min(z[x],w[x]);
return;
}
void dp(ll x,ll mins){
ll c=mins,zc=mins;
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(z[y]<c)zc=c,c=z[y];
else if(z[y]<zc)zc=z[y];
}
if(f[x]){
for(ll i=ls[x];i;i=a[i].next)
dp(a[i].to,(z[a[i].to]==c)?zc:c);
if(c!=1e9+7)ans=min(ans,w[x]*A+c*B);
}
else if(s[x]==1){
for(ll i=ls[x];i;i=a[i].next)
if(f[a[i].to])dp(a[i].to,(z[a[i].to]==c)?zc:c);
}
}
signed main()
{
T=read();
while(T--){
n=read();t=read();A=read();B=read();
for(ll i=1;i<=n;i++)ls[i]=0;tot=0;
for(ll i=2;i<=n;i++)fa[i]=read(),addl(fa[i],i);
for(ll i=1;i<=n;i++)w[i]=read();
dfs(1);
if(f[1]^t^1){puts("0");continue;}
else{
ans=3e18;dp(1,1e9+7);
if(ans==3e18) puts("-1");
else printf("%lld\n",ans);
}
}
}

P7443-加边【博弈论】的更多相关文章

  1. 博弈论入门小结 分类: ACM TYPE 2014-08-31 10:15 73人阅读 评论(0) 收藏

    文章原地址:http://blog.csdn.net/zhangxiang0125/article/details/6174639 博弈论:是二人或多人在平等的对局中各自利用对方的策略变换自己的对抗策 ...

  2. 博弈论之Nim

    博弈论(一):Nim游戏 重点结论:对于一个Nim游戏的局面(a1,a2,...,an),它是P-position当且仅当a1^a2^...^an=0,其中^表示位异或(xor)运算. Nim游戏是博 ...

  3. 博弈论中的Nim博弈

    瞎扯 \(orzorz\) \(cdx\) 聚聚给我们讲了博弈论.我要没学上了,祝各位新年快乐.现在让我讲课我都不知道讲什么,我会的东西大家都会,太菜了太菜了. 马上就要回去上文化课了,今明还是收下尾 ...

  4. 博弈论简单入门sb总结

    博弈论简单入门sb总结 下午讲博弈论.没预习,GG. 整个下午都在学. 0 有一堆共n个石子,两个人轮流取石子,每个人一次可以取1到k个,取到最后一个石子的人胜利. 小学生都会的sb题.若k+1|n, ...

  5. 【uoj#51】[UR #4]元旦三侠的游戏 博弈论+dp

    题目描述 给出 $n$ 和 $m$ ,$m$ 次询问.每次询问给出 $a$ 和 $b$ ,两人轮流选择:将 $a$ 加一或者将 $b$ 加一,但必须保证 $a^b\le n$ ,无法操作者输,问先手是 ...

  6. [您有新的未分配科技点]博弈论进阶:似乎不那么恐惧了…… (SJ定理,简单的基础模型)

    这次,我们来继续学习博弈论的知识.今天我们会学习更多的基础模型,以及SJ定理的应用. 首先,我们来看博弈论在DAG上的应用.首先来看一个小例子:在一个有向无环图中,有一个棋子从某一个点开始一直向它的出 ...

  7. [您有新的未分配科技点]博弈论入门:被博弈论支配的恐惧(Nim游戏,SG函数)

    今天初步学习了一下博弈论……感觉真的是好精妙啊……希望这篇博客可以帮助到和我一样刚学习博弈论的同学们. 博弈论,又被称为对策论,被用于考虑游戏中个体的预测行为和实际行为,并研究他们的应用策略.(其实这 ...

  8. 三十分钟理解博弈论“纳什均衡” -- Nash Equilibrium

    欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术感兴趣的同学加入. 纳什均衡(或者纳什平衡),Nash ...

  9. xtuoj 1235 CQRXLB(博弈论)

    CQRXLB Accepted : 19   Submit : 40 Time Limit : 1000 MS   Memory Limit : 65536 KB CQRXLB Problem Des ...

  10. HDU 5299 Circles Game 博弈论 暴力

    Circles Game 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5299 Description There are n circles on ...

随机推荐

  1. TDSQL MySQL版基本原理-水平分表 读写分离 弹性扩展 强同步

    TDSQL MySQL版(TDSQL for MySQL)是部署在腾讯云上的一种支持自动水平拆分.Shared Nothing 架构的分布式数据库.TDSQL MySQL版 即业务获取的是完整的逻辑库 ...

  2. 微信公众号授权回调用户信息,获取openid

    1.--------------------用户授权登录并获取code 授权登录方式有两个,一种为静默授权登录(scope=snsapi_base),一种为非静默授权登录(scope=snsapi_u ...

  3. 手撕LRU缓存了解一下

    面试官:来了,老弟,LRU缓存实现一下? 我:直接LinkedHashMap就好了. 面试官:不要用现有的实现,自己实现一个. 我:..... 面试官:回去等消息吧.... 大家好,我是程序员学长,今 ...

  4. Python中的文件处理和数据存储json

    前言:每当需要分析或修改存储在文件中的信息时,读取文件都很有用,对数据分析应用程序来说尤其如此. 例如,你可以编写一个这样的程序:读取一个文本文件的内容,重新设置这些数据的格式并将其写入文件,让浏览器 ...

  5. C#使用异步需要注意的几个问题

    C#异步使用需要注意的几个问题1.异步方法如果只是对别的方法的简单的转发调用,没哟复杂的逻辑(比如等待A的结果,再调用B,等待A调用的返回值拿到内部做一些处理再返回),那么就可以去掉async关键字. ...

  6. shell脚本之case语句

    case ... esac 为多选择语句,与其他语言中的 switch ... case 语句类似,是一种多分枝选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行 ...

  7. Easy-ARM IMX283 移植RTL8192CU驱动

    测试平台 宿主机平台:Ubuntu 12.04.4 LTS 目标机:Easy-ARM IMX283 目标机内核:Linux 2.6.35.3 无线网卡驱动下载地址:http://www.comfast ...

  8. Appium问题解决方案(4)- Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncException

    背景 操作步骤 运行 uiautomatorviewer.bat 点击左上角的 Device ScreensShot 报错 截图 解决方法 网上还是有很多方法的,可能造成的原因不同,我是第六种方法解决 ...

  9. 显示锁lock

    一.内置锁sync 和 显示锁lock概念 1.synv锁又叫内置锁,不能中断,拿不到无限等待即阻塞: java自带关键字: 隐式可重入: 重入锁:锁对应对象要多次调用对应方法,如递归 2. lock ...

  10. CUDA 矩阵乘法终极优化指南

    作者:马骏 | 旷视 MegEngine 架构师 前言 单精度矩阵乘法(SGEMM)几乎是每一位学习 CUDA 的同学绕不开的案例,这个经典的计算密集型案例可以很好地展示 GPU 编程中常用的优化技巧 ...