1. 程式人生 > 實用技巧 >[AGC005E] Sugigma: The Showdown

[AGC005E] Sugigma: The Showdown

題意

傳送門

思路

不會博弈

首先要是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了