[AGC005E] Sugigma: The Showdown
阿新 • • 發佈:2020-12-28
題意
思路
不會博弈
首先要是A能走到一條邊 \((u,v)\) 滿足 \(disb(u,v) \ge 3\) 那麼A就可以在這倆個點之間伺機流竄,這個時候遊戲無限。
在去掉這些邊以後,A就無法跨越B所在的點了。因為剩下的情況中B都可以一步走到。也就是說,B會向某一個子樹的葉節點不斷逼近,那麼A能做的,就是儘量走到離 \(S_b\) 最遠的且能到達的(\(disa(S_a,x) <disb(S_b,x)\))那個葉節點,等著B結束遊戲
那麼只要用dfs搜尋一遍就好了,碰見無限邊就輸出 \(-1\) 即可
#include <bits/stdc++.h> const int N=200005; int edge,Next[N<<1],to[N<<1],last[N],f[N],dep[N],ans,tag[N],n,s,t,x,y; std::vector<int> e[N]; void add(int x,int y){ to[++edge]=y; Next[edge]=last[x]; last[x]=edge; } void dfs(int x,int y){ f[x]=y; for (int i=last[x];i;i=Next[i]){ int u=to[i]; if (u==y) continue; dep[u]=dep[x]+1; dfs(u,x); } } bool chk(int x,int y){ if (dep[x]<dep[y]) std::swap(x,y); if (dep[x]==dep[y]) return f[x]==f[y]; if (dep[x]==dep[y]+1) return f[x]==y; if (dep[x]==dep[y]+2) return f[f[x]]==y; return 0; } void dfs2(int x,int y,int deep){ if (deep>=dep[x]) return; if (tag[x]){ puts("-1"); exit(0); } ans=std::max(ans,dep[x]); for (auto u:e[x]){ if (u==y) continue; dfs2(u,x,deep+1); } } int main(){ scanf("%d%d%d",&n,&s,&t); if (s==t){ puts("0"); return 0; } for (int i=1;i<n;i++){ scanf("%d%d",&x,&y); e[x].push_back(y); e[y].push_back(x); } for (int i=1;i<n;i++){ scanf("%d%d",&x,&y); add(x,y),add(y,x); } dfs(t,0); for (int i=1;i<=n;i++) for (auto j:e[i]) if (!chk(i,j)){ tag[i]=1; break; } dfs2(s,0,0); printf("%d\n",ans*2); }
後記
震驚!鴿子竟然寫blog了