• 洛谷 P3398 仓鼠找sugar 题解


    先说一下题意:

    在一颗树上一个仓鼠从a走到b,一个他的基友从c走到d求他两个是不是会有相遇的地方。

    一道求lca的题目。

    这道题只看题目是很难找出规律的,但是一画图他的规律就很显然了

    可以发现如果两条路径如果相交那一对点的最近公共祖先一定在另一台的路径上

    不然如果相交那就这能两条边交叉,这在树中是不可能出现的
    否则就不是一棵树

    但是怎么确定这到底是不是回相遇的呢?

    可以先求出仓鼠目的地b和出发点a的最近公共祖先qwq和surger的

    目的地d和出发点c的最近公共祖先awa

    然后分别求出a和d,a和c,b和d,b和c的最近公共祖先来和

    前面求出的两个最近公共祖先的深度比较如果有一个这两个

    深度小那就是不可行的不然如果都比他深度深或者等于的话

    那就是可能遇见的

    但是怎么证明只要他们的最近公共祖先的深度大于等于awa和qwq

    那就是可行的呢?

    这个在三克油大佬的博客里面已经证明的很好啦,我就不多说了
    附上链接

    这里

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    
    using namespace std;
    const int Max = 100005;
    struct node
    {
    	int y,ne;
    }a[Max << 1];
    int head[Max];
    int f[Max][22];
    int tot = 0;
    void insert(int x,int y)
    {
    	a[++ tot].y = y;
    	a[tot].ne = head[x];
    	head[x] = tot;
    }
    bool use[Max];
    int de[Max];
    void dfs(int x)
    {
    	use[x] = true;
    	for(int i = head[x];i != 0;i = a[i].ne)
    	{
    		int ii = a[i].y;
    		if(use[ii] == false)
    		{
    			f[ii][0] = x;
    			de[ii] = de[x] + 1;
    			dfs(ii);
    		}
    	}
    }
    
    int lca(int x,int y)
    {
    	if(de[x] < de[y])swap(x,y);
    	for(int j = 20;j >= 0;j --)
    		if(de[f[x][j]] >= de[y])
    			x = f[x][j];
    	if(x == y)
    		return x;
    	for(int i = 20;i >= 0;i --)
    		if(f[x][i] != f[y][i])
    			x = f[x][i],y = f[y][i];
    	return f[x][0];
    }
    
    int main()
    {
    	int n,q;
    	int x,y;
    	scanf("%d%d",&n,&q);
    	for(int i = 1;i < n;++ i)
    	{
    		scanf("%d%d",&x,&y);
    		insert(x,y);
    		insert(y,x);
    	}
    	de[1] = 1;
    	dfs(1);
    	for(int j = 1;j <= 20;j ++)
    		for(int i = 1;i <= n;++ i)
    			f[i][j] = f[f[i][j - 1]][j - 1];
    	while(q --)
    	{
    		int aa,bb,cc,dd;
    		scanf("%d%d%d%d",&aa,&bb,&cc,&dd);
    		int ab = lca(aa,bb);
    		int cd = lca(cc,dd);
    		
    		//int ac = lca(aa,cc);
    		//int ad = lca(aa,dd);
    		//int bc = lca(bb,cc);
    		//int bd = lca(bb,dd);
    		int ans = max(de[lca(aa,cc)],de[lca(aa,dd)]);
    		ans = max(ans,de[lca(bb,cc)]);
    		ans = max(ans,de[lca(bb,dd)]);
    		if(ans >= de[ab] && ans >= de[cd])
    			cout<<"Y"<<endl;
    		else
    			cout<<"N"<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    Leetcode 538. Convert BST to Greater Tree
    Leetcode 530. Minimum Absolute Difference in BST
    Leetcode 501. Find Mode in Binary Search Tree
    Leetcode 437. Path Sum III
    Leetcode 404. Sum of Left Leaves
    Leetcode 257. Binary Tree Paths
    Leetcode 235. Lowest Common Ancestor of a Binary Search Tree
    Leetcode 226. Invert Binary Tree
    Leetcode 112. Path Sum
    Leetcode 111. Minimum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/acioi/p/11524117.html
Copyright © 2020-2023  润新知