AtCoder AGC005E Sugigma: The Showdown (博弈论)

题目链接

https://atcoder.jp/contests/agc005/tasks/agc005_e

题解

完了真的啥都不会了……

首先,显然如果某条A树的边对应B树上的距离大于等于(3), 且A能走到该边的某个端点,那么答案就是(-1).
A能走到某个点当且仅当从A的起点到这个点的路径上每个点与A起点的距离都小于与B起点的距离。
然后直接在A树上从根开始DFS,如果走不到了就返回,否则用与(y)的距离更新答案;同时在遍历每条边的时候判断是否可以(-1).
时间复杂度(O(nlog n)), 但是由于距离不超过(3)的特殊性可以优化成(O(n)).

上面的性质我都发现了,可是我做不出来这题……到底是什么情况……

代码

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cassert>
using namespace std;

const int N = 2e5;
const int lgN = 18;
const int INF = 1e7;
struct Edge
{
	int v,nxt;
} e1[(N<<1)+3],e2[(N<<1)+3];
int fe1[N+3],fe2[N+3];
int dep1[N+3],dep2[N+3];
int fa2[N+3][lgN+3];
int n,en1,en2,s1,s2,ans;

void addedge1(int u,int v)
{
	en1++; e1[en1].v = v;
	e1[en1].nxt = fe1[u]; fe1[u] = en1;
}
void addedge2(int u,int v)
{
	en2++; e2[en2].v = v;
	e2[en2].nxt = fe2[u]; fe2[u] = en2;
}

void dfs1(int u,int prv)
{
	for(int i=fe1[u]; i; i=e1[i].nxt)
	{
		int v = e1[i].v;
		if(v==prv) continue;
		dep1[v] = dep1[u]+1;
		dfs1(v,u);
	}
}

void dfs2(int u)
{
	for(int i=1; i<=lgN; i++) fa2[u][i] = fa2[fa2[u][i-1]][i-1];
	for(int i=fe2[u]; i; i=e2[i].nxt)
	{
		int v = e2[i].v;
		if(v==fa2[u][0]) continue;
		fa2[v][0] = u; dep2[v] = dep2[u]+1;
		dfs2(v);
	}
}

int LCA(int u,int v)
{
	if(dep2[u]<dep2[v]) swap(u,v);
	int dif = dep2[u]-dep2[v];
	for(int i=0; i<=lgN; i++)
	{
		if(dif&(1<<i)) {u = fa2[u][i];}
	}
	if(u==v) return u;
	for(int i=lgN; i>=0; i--)
	{
		if(fa2[u][i]!=fa2[v][i]) {u = fa2[u][i],v = fa2[v][i];}
	}
	return fa2[u][0];
}

void dfs(int u,int fa)
{
	if(dep1[u]>=dep2[u]) {return;}
	ans = max(ans,dep2[u]);
	for(int i=fe1[u]; i; i=e1[i].nxt)
	{
		int v = e1[i].v;
		if(v==fa) continue;
		if(dep2[u]+dep2[v]-2*dep2[LCA(u,v)]>2) {ans = INF; return;}
		dfs(v,u);
	}
}

int main()
{
	scanf("%d%d%d",&n,&s1,&s2);
	for(int i=1; i<n; i++)
	{
		int u,v; scanf("%d%d",&u,&v);
		addedge1(u,v); addedge1(v,u);
	}
	for(int i=1; i<n; i++)
	{
		int u,v; scanf("%d%d",&u,&v);
		addedge2(u,v); addedge2(v,u);
	}
	dfs1(s1,0); dfs2(s2);
	ans = 0; dfs(s1,0);
	printf("%d
",ans==INF?-1:ans*2);
	return 0;
}
原文地址:https://www.cnblogs.com/suncongbo/p/11534122.html