• luogu 3398 仓鼠找sugar


    题目描述

    小仓鼠的和他的基(mei)友(zi)(sugar)住在地下洞穴中,每个节点的编号为(1~n)。地下洞穴是一个树形结构。这一天小仓鼠打算从从他的卧室((a))到餐厅((b)),而他的基友同时要从他的卧室((c))到图书馆((d))。他们都会走最短路径。现在小仓鼠希望知道,有没有可能在某个地方,可以碰到他的基友?

    小仓鼠那么弱,还要天天被zzq大爷虐,请你快来救救他吧!

    输入输出格式

    输入格式
    第一行两个正整数(n)(q),表示这棵树节点的个数和询问的个数。

    接下来(n-1)行,每行两个正整数(u)(v),表示节点u到节点v之间有一条边。

    接下来(q)行,每行四个正整数(a)(b)(c)(d),表示节点编号,也就是一次询问,其意义如上。

    输出格式
    对于每个询问,如果有公共点,输出大写字母“Y”;否则输出“N”。

    输入输出样例
    **输入样例#1: **
    5 5
    2 5
    4 2
    1 3
    1 4
    5 1 5 1
    2 2 1 4
    4 1 3 4
    3 1 1 5
    3 5 1 4
    输出样例#1:
    Y
    N
    Y
    Y
    Y

    说明

    本题时限1s,内存限制128M,因新评测机速度较为接近NOIP评测机速度,请注意常数问题带来的影响。

    20%的数据$ nle200,qle200$

    40%的数据 (nle2000,qle2000)

    70%的数据 (nle50000,qle50000)

    100%的数据 (nle100000,qle100000)

    solution

    这道题用裸的树剖求(LCA)就可以做出来。
    但是我们要判断如何在两天路径上找相同的点。
    经过多次画图发现,一条路径上的(LCA)一定会出现在另一条路径上。
    所以我们就可以求(LCA)
    那么我们需要判断哪两个条件呢?
    设当前点(x),判断在(a)(b)这条路径上

    1. deep[LCA(a,b)]>deep[LCA(c,d)]
    2. LCA(LCA(a,b),c)==LCA(a,b)||LCA(LCA(a,b),d)==LCA(a,b)
    

    这两个条件的意思是
    如果(LCA1)(LCA2)要深,并且LCA2两个点中其中一个经过LCA1,那么就在一条路径上

    code

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N = 200000;
    int n,q;
    struct edge {
    	int next,to;
    } e[N];
    int head[N],tot,deep[N],fa[N],size[N],top[N],son[N],id[N],cnt,ind[N],root;
    void add(int x,int y) {
    	e[++tot].next=head[x];
    	head[x]=tot;
    	e[tot].to=y;
    }
    void dfs1(int x,int f) {
    	fa[x]=f;
    	size[x]=1;
    	for(int i=head[x]; i; i=e[i].next) {
    		int v=e[i].to;
    		if(v!=f && !deep[v]) {
    			deep[v]=deep[x]+1;
    			dfs1(v,x);
    			size[x]=size[v]+size[x];
    			if(size[v]>size[son[x]]) son[x]=v;
    		}
    	}
    }
    void dfs2(int x,int topf) {
    	id[x]=++cnt;
    	top[x]=topf;
    	if(!son[x]) return;
    	dfs2(son[x],topf);
    	for(int i=head[x]; i; i=e[i].next) {
    		int v=e[i].to;
    		if(v!=fa[x] && !id[v])
    			dfs2(v,v);
    	}
    }
    int LCA(int x,int y) {
    	while(top[x]!=top[y]) {
    		if(deep[top[x]]<deep[top[y]]) swap(x,y);
    		x=fa[top[x]];
    	}
    	return deep[x]<=deep[y]? x:y;
    }/*
    bool judge(int lca,int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            x=fa[top[x]];
            if(x==lca)return true;
        }
        return false;
    }*/
    int main() {
    	cin >> n >> q;
    	for(int i=1; i<=n-1; i++) {
    		int a,b;
    		cin >> a >> b;
    		add(a,b);
    		add(b,a);
    	}
    	root=1;
    	deep[1]=1;
    	dfs1(1,1);
    	dfs2(1,1);
    	while(q--) {
    		int a,b,c,d;
    		cin >> a >> b >> c >> d;
    		int S=LCA(a,b);
    		int T=LCA(c,d);
    		if(deep[S]<deep[T]){
    			swap(a,c);
    			swap(b,d);
    			swap(S,T);
    		}
    		if(LCA(S,c)==S||LCA(S,d)==S)puts("Y");
    		else puts("N");
    	}
    }
    
  • 相关阅读:
    面试笔记1
    Hello World!!
    百度地图API JavaScript显示人员分布信息
    MUI Picker选择器 自定义省市地址三级联动
    【Unity】Lua热重载
    【临时存放】变量配置
    SVN代码管理出现注册错误
    javaweb学习
    微信应用号(微信小程序)开发教程
    shell脚本时间运算
  • 原文地址:https://www.cnblogs.com/ifmyt/p/9495177.html
Copyright © 2020-2023  润新知