版本分支 蓝桥杯国赛2018 离线LCA Tarjin

135 阅读2分钟

题目描述

小明负责维护公司一个奇怪的项目。这个项目的代码一直在不断分支(branch)但是从未发生过合并(merge)。

现在这个项目的代码一共有 N 个版本,编号 1 ~ N,其中 1 号版本是最初的版本。

除了 1 号版本之外,其他版本的代码都恰好有一个直接的父版本;即这 NNN 个版本形成了一棵以 1 为根的树形结构。

如下图就是一个可能的版本树:

1

/ \

2 3

\ / \

5 4 6

现在小明需要经常检查版本 x 是不是版本 y 的祖先版本。你能帮助小明吗? 输入描述

第一行包含两个整数 N,Q代表版本总数和查询总数。

以下 N - 1 行,每行包含 2 个整数 u 和 v ,代表版本 u 是版本 v 的直接父版本。

再之后 Q 行,每行包含 2 个整数 x 和 y ,代表询问版本 x 是不是版本 y 的祖先版本。

其中,1≤N≤10e5,1≤Q≤1051 \leq N \leq 10^5, 1 \leq Q \leq 10^51≤N≤105,1≤Q≤105。

输出描述

对于每个询问,输出 YES 或 NO 代表 xxx 是否是 yyy 的祖先。

输入输出样例

输入 6 5 1 2 1 3 2 5 3 6 3 4 1 1 1 4 2 6 5 2 6 4 输出 YES YES NO NO NO

在这里插入图片描述

AC代码

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Scanner;
import java.util.Vector;

public class Main {
	static Vector<Integer> v[];
	static Vector<Integer> q[];
	static Vector<Integer> q_id[];
	static int vis[];
	static int ans[];
	static int fa[];// f[x] = y;x的父亲是y
	static int x[];
	static int find(int x) {
		if (x == fa[x])
			return x;
		return fa[x] = find(fa[x]);
	}

//    v=2, 表示已经访问完了,而且还回溯了,即它的子节点已经全部访问过了
//    v=1, 表示访问过,但是还没有回溯,即现在在访问它的子节点
//    v=0, 表示还没有访问过

	static void tarjan(int x) {
		vis[x] = 1;
		for(int i = 0;i < v[x].size();i++) {
			int y  = v[x].get(i);
			if(vis[y] != 0) continue;
			tarjan(y);
			fa[y] = x;
		}
		for(int i = 0;i < q[x].size();i++) {
			int y  = q[x].get(i), id = q_id[x].get(i);
			if(vis[y] == 2) {
				ans[id] = find(y);
			}
		}
		vis[x] = 2;
	}

	public static void main(String[] args) throws IOException {
		Scanner cin = new Scanner(System.in);
		int n = cin.nextInt();
		int m = cin.nextInt();
		v = new Vector[n + 5];
		q = new Vector[n + 5];
		q_id = new Vector[n + 5];
		x = new int[n + 5];
		vis = new int[n + 5];
		fa = new int[n + 5];
		ans = new int[m + 5];
		
		for (int i = 1; i <= n; i++) {
			v[i] = new Vector<>();
			q[i] = new Vector<>();
			q_id[i] = new Vector<>();
		}
		for(int i = 1;i <= n;i++)fa[i] = i;
		for (int i = 1; i <= n - 1; i++) {
			int x = cin.nextInt();
			int y = cin.nextInt();
			v[x].add(y);
			v[y].add(x);
		}
		for (int i = 1; i <= m; i++) {
			int a = cin.nextInt();
			x[i] = a;
			int b = cin.nextInt();
			if(a == b) ans[i] = a;
			q[a].add(b);
			q[b].add(a);
			q_id[a].add(i);
			q_id[b].add(i);
		}
		tarjan(1);
		for(int i = 1;i <= m;i++)
			System.out.println(ans[i] == x[i] ? "YES" : "NO");
	
	}

}