AT2063 [AGC005E] Sugigma: The Showdown 題解
阿新 • • 發佈:2021-07-20
完全不會做。
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\)
同時,如果 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; }