无向图_最近祖先问题

最近公共祖先问题

时间限制: 1 Sec   内存限制: 128 MB

题目描述

已知一个无向图和若干个节点,且该无向图是连通无环图。

请以节点1作为根节点,输出任意两节点的最近公共祖先(Least Common Ancestor)

子树的个数可以有任意多个,不一定是二叉树

输入

图的节点数m和边n,询问数q

边的信息:每一条边(1,2)表示节点1连接到节点2(n行)

询问信息:1 2,询问节点1和节点2的LCA(q行)


输出

节点的LCA

样例输入

12 11 4
1 2
2 5
6 5
1 4
1 3
7 3
3 8
8 9
8 10
9 11
10 12

1 9
2 6
9 7
12 4

样例输出

1
2
3
1



import java.util.Scanner;

public class Main {

	static int n, e, q;
	static boolean edges[][];
	static boolean marked[];
	static String res = "";
	static int way[][];
	static int step = 0;
	static int flag = 0;
	static int sign[];

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		e = in.nextInt();
		q = in.nextInt();
		edges = new boolean[n + 1][n + 1];
		marked = new boolean[n + 1];
		way = new int[n + 1][n + 1];
		sign = new int[n + 1];
		for (int i = 0; i < e; i++) {
			int x = in.nextInt();
			int y = in.nextInt();
			edges[x][y] = true;
			edges[y][x] = true;
		}
		for (int i = 0; i < q; i++) {
			int x = in.nextInt();
			int y = in.nextInt();

			if (way[x][0] != 1) {
				dfs(1, x);
				reset();
			}
		//	System.out.println("x=" + x + Arrays.toString(way[x]));
			if (way[y][0] != 1) {
				dfs(1, y);
				reset();
			}
			//System.out.println("y=" + y + Arrays.toString(way[y]));
			outer:for(int j=n;j>=0;j--) {
				if(way[x][j]==0)continue;
				for(int k=n;k>=0;k--) {
					if(way[x][j]==way[y][k]) {
						System.out.println(way[x][j]);
						break outer;
					}
				}
			}

		}
		in.close();
	}

	//深度优先搜索
	private static void dfs(int x, int y) {
		if (flag == 1) {
			return;
		}
		//System.out.println("x="+x+"  step="+step);
		marked[x] = true;
		way[y][step] = x;

		if (x == y) {
			flag = 1;
			return;
		}

		for (int i = 1; i <= n; i++) {
			if (edges[x][i] == true && marked[i] == false) {
				sign[x] = 1;
				step++;
				dfs(i, y);
			}
			if (i == n && sign[x] == 0) {
				way[y][step] = 0;
				step--;
				if (step >= 1) {
					sign[way[y][step]] = 0;
				}
			}
		}
	}

	private static void reset() {
		step = 0;
		flag = 0;
		for (int j = 0; j <= n; j++) {
			marked[j] = false;
			sign[j] = 0;
		}
	}
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值