zoukankan      html  css  js  c++  java
  • AT2063 [AGC005E] Sugigma: The Showdown 题解

    ATcoder
    Luogu

    Description.

    完全不会做。

    Alice 和 Bob 在打隔膜,有两棵树,分别命名为 A 树和 B 树。
    两棵树上分别有两颗棋子,每次 Alice 和 Bob 分别可以移动棋子到相邻的节点。
    Bob 想追上 Alice 的棋子即让他们棋子所在节点编号相同,Alice 则不希望。
    问最大步数,或输出 -1 代表永远也追不上。

    Solution.

    先考虑追不上的情况,显然是 Alice 只需要轻轻一步,就可以在 B 树上跳很远,Bob 顾左不顾右,追不上。
    抽象地说,就是 A 树上存在一对相邻的节点,它们在 B 树上距离大于等于三,且 Alice 在被 Bob 追上前能到达它。

    接着考虑 Alice 能到达哪些点,注意这题中 Alice 和 Bob 可以原地等待。
    所以 Alice 是无法越过 Bob 的,即相对位置一定不变,否则 Alice 就已经无敌了。
    (手模以下我们会发现如果 Alice 步长为 \(2\),那 Bob 必定可以等在 Alice 要到的两个点 “守株待兔”。
    同时,如果 Alice 想让 Bob 猜不到他下一步会往哪走,Bob 就可以原地等待。
    Alice 不可能使用 “迂回” 的战略,因为如果他迂回,Bob 往他那个方向继续追,Alice 要么无法回来,要么直接被困死。
    所以 Bob 会 “步步相逼”,把 Alice 逼入死胡同。
    以上分析的出的结论就是,如果 Alice 走直线到这个点所用时间小于等于 Bob 的,那 Alice 必然到不了这个点。

    所以我们首先判断一下每个点是不是 “Alice 无敌点”,然后 Alice 按照向所有可以走到的方向前进。
    Alice 必定会找到一个可以走到的位置,然后在那里原地等死,所以只需要找到 Bob 走到 Alice 可达点的最长距离即可。

    Coding.

    判断两个点距离是否大于三我竟然直接用了个倍增 LCA,不愧是我!

    点击查看逊人代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }/*}}}*/
    const int N=200005;struct edge{int to,nxt;}e[N<<1];int et,head[N];
    int n,X,Y,da[N],db[N],fr[N],tw[N],f[N][20],rs;char fg[N];
    inline void adde(int x,int y) {e[++et]=(edge){y,head[x]},head[x]=et;}
    inline void dfs0(int x,int fa)
    {
    	f[x][0]=fa;for(int i=1;i<20;i++) f[x][i]=f[f[x][i-1]][i-1];
    	for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa) db[e[i].to]=db[x]+1,dfs0(e[i].to,x);
    }
    inline int LCA(int x,int y)
    {
    	if(db[x]<db[y]) swap(x,y);
    	for(int i=19;~i;i--) if(db[f[x][i]]>=db[y]) x=f[x][i];
    	for(int i=19;~i;i--) if(f[x][i]^f[y][i]) x=f[x][i],y=f[y][i];
    	return x^y?f[x][0]:x;
    }
    inline int dis(int x,int y) {return db[x]+db[y]-(db[LCA(x,y)]<<1);}
    inline void dfs1(int x,int fa)
    {
    	if(fg[x]) puts("-1"),exit(0);else rs=max(rs,db[x]);
    	for(int i=head[x];i;i=e[i].nxt) if(e[i].to!=fa)
    		{da[e[i].to]=da[x]+1;if(da[e[i].to]<db[e[i].to]) dfs1(e[i].to,x);}
    }
    signed main()
    {
    	read(n),read(X),read(Y);for(int i=1;i<n;i++) read(fr[i]),read(tw[i]);
    	for(int i=1,x,y;i<n;i++) read(x),read(y),adde(x,y),adde(y,x);
    	dfs0(Y,0);for(int i=1;i<n;i++) if(dis(fr[i],tw[i])>2) fg[fr[i]]=fg[tw[i]]=1;
    	et=0,memset(head,0,sizeof(head));for(int i=1;i<n;i++) adde(fr[i],tw[i]),adde(tw[i],fr[i]);
    	return dfs1(X,0),printf("%d\n",rs<<1),0;
    }
    
  • 相关阅读:
    今天一天看一天文档
    ImportError: No module named _md5解决方案
    Spelling Corrector & sphinx typo search
    linux下使用ipython的pylab模式时不显示图形的问题解决方案
    error: error in setup script: command 'build_exe' has no such option 'includefiles'
    【转】oracle之包的创建和应用
    ADO.NET 与 ORACLE
    SQL注入大全
    【转】oracle之循环语法
    ASP.NET 防止按钮多次提交解决方法
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15034601.html
Copyright © 2011-2022 走看看