zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    springboot使用hibernate validator校验
    @Inherited:允许子类继承父类的注解。
    springboot跨域配置
    spring boot——MockMvc的用法 (SpringBoot 1.5.18)下测试通过
    spring boot(10) 基础学习内容
    关于Spring @RequestBody 自动映射模型原理
    @Requestbody@ApiParam @PathVariable @RequestParam三者区别
    《生成对抗网络入门指南【2】》
    《生成对抗网络入门指南【1】》
    《精通 CSS3 动画(学完这个课写炫酷页面)》
  • 原文地址:https://www.cnblogs.com/suncongbo/p/11534122.html
Copyright © 2011-2022 走看看