博弈
来源:互联网 发布:手机淘宝售后退款流程 编辑:程序博客网 时间:2024/06/06 01:08
题目大意
给定一棵n个节点的树。两个人进行博弈,后手的人最初在节点b上,还给定一个目标节点t。
对于后手的人,如果有至少一条未被标记的边连着它所在的节点,那么它必须选择其中一条走过去,并标记下这条边。否则不用动。
对于先手的人,每次可以:1. 删除一条边 2. 删除一条边的标记 3. 不操作。
现在先手者想以最少的操作次数把后手者赶到目标节点(不操作不计算次数),后手者则想最大化这个答案。两个人绝顶聪明,问最少操作次数。
分析
可以把这棵树看成是以t为根的有根树。
首先考虑b和t直接相连的情况。后手者显然是第一步必须往下走。那么先手者要做的就是删去通往操作次数最多的子树的路,然后后手者走次多的子树。然后不断反复直到跑到底。
跑到底后就变成一个有趣的情况了~后手不能动,那么先手可以通过一波操作,使得后手者后来一定是往父亲跑直到走到t。
那么可以设f[i]表示走到i为根的子树的答案。如果它是叶子就直接是它跑到父亲的答案,只有一个儿子就是它+1,否则就是删去f最大的儿子。可以O(n)计算f[]。
现在考虑到b可能不是t的直接儿子,后手者可以跑到一个祖先,然后再进入子树变成上面的情况。
但是我们不需要知道具体的方案!考虑二分答案,然后从下往上枚举那些子树,设B表示当前子树之前的子树需要砍掉多少个,那么如果B+f[i]>mid,就表示这个子树要被砍掉。砍掉它后如果B>dis(b,i),就表示当前能提供的删边次数不足以砍掉这个子树,那么mid偏小了。
时间复杂度
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N=2e6+5;typedef long long LL;int n,tot,B,T,h[N],e[N],nxt[N],f[N],D[N],fa[N],g[N],cnt[N];bool bz[N];char c;int read(){ int x=0,sig=1; for (c=getchar();c<'0' || c>'9';c=getchar()) if (c=='-') sig=-1; for (;c>='0' && c<='9';c=getchar()) x=x*10+c-48; return x*sig;}void add(int x,int y){ e[++tot]=y; nxt[tot]=h[x]; h[x]=tot;}bool check(int mid){ int s=0,d=1,k,i,j; for (i=T;i!=B;i=fa[i],d++) { for (j=h[i],k=0;j;j=nxt[j]) if (!bz[e[j]]) { if (s+f[e[j]]>mid) { k++; if (s+k>d) return 0; } } s+=k; } return s<=mid;}int main(){ n=read(); B=read(); T=read(); for (int i=1;i<n;i++) { int x=read(),y=read(); add(x,y); add(y,x); } D[tot=1]=B; for (int i=1;i<=tot;i++) { int x=D[i]; for (int j=h[x];j;j=nxt[j]) if (e[j]!=fa[x]) { fa[e[j]]=x; D[++tot]=e[j]; } } for (int i=T;i;i=fa[i]) bz[i]=1; for (int i=2;i<=tot;i++) { int x=D[i]; for (int j=h[x];j;j=nxt[j]) if (e[j]!=fa[x] && !bz[e[j]]) cnt[x]++; g[x]=g[fa[x]]+cnt[x]; } for (int i=tot;i;i--) { int x=D[i],m1=0,m2=0; if (bz[x]) continue; f[x]=0; for (int j=h[x];j;j=nxt[j]) if (e[j]!=fa[x]) { if (f[e[j]]>m1) { m2=m1; m1=f[e[j]]; }else if (f[e[j]]>m2) m2=f[e[j]]; } if (cnt[x]<2) f[x]=g[x];else f[x]=m2; } int l,r,mid; for (l=0,r=n,mid=l+r>>1;l<r;mid=l+r>>1) { if (check(mid)) r=mid;else l=mid+1; } printf("%d\n",l); return 0;}
阅读全文
0 0
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 博弈
- 蚁群算法路径规划TSP
- pickle/cPickle操作函数、对象及在ROS中发布复杂消息
- Spring @Configuration 和 @Component 区别
- python-爬取淘宝商品
- Android 终端的退出
- 博弈
- php -- PDO属性设置
- 文本处理工具awk
- C中的struct与C++中的struct区别以及C++中的struct与C++中的class的区别
- 如何部署vuejs项目到Tomcat上
- 腾讯大规模Hadoop集群实践 [转程序员杂志]
- git merge-快进合并和非快进合并
- iOS修改UITextField的placeholder的字体颜色大小
- java nio