1. 程式人生 > >#1062 : 最近公共祖先·一

#1062 : 最近公共祖先·一

輸入

每個測試點(輸入檔案)有且僅有一組測試資料。

每組測試資料的第1行為一個整數N,意義如前文所述。

每組測試資料的第2~N+1行,每行分別描述一對父子關係,其中第i+1行為兩個由大小寫字母組成的字串Father_i, Son_i,分別表示父親的名字和兒子的名字。

每組測試資料的第N+2行為一個整數M,表示小Hi總共詢問的次數。

每組測試資料的第N+3~N+M+2行,每行分別描述一個詢問,其中第N+i+2行為兩個由大小寫字母組成的字串Name1_i, Name2_i,分別表示小Hi詢問中的兩個名字。

對於100%的資料,滿足N<=10^2,M<=10^2, 且資料中所有涉及的人物中不存在兩個名字相同的人(即姓名唯一的確定了一個人)。

輸出

對於每組測試資料,對於每個小Hi的詢問,輸出一行,表示查詢的結果:如果根據已知資訊,可以判定詢問中的兩個人存在共同的祖先,則輸出他們的所有共同祖先中輩分最低的一個人的名字,否則輸出-1。

思路:

先用其中一個來回溯到根,記錄路徑上的節點為訪問過,再用另一個來回溯到根,期間只要第一次碰到已經訪問過的節點,就是答案(不可以同時回溯)
public class Main {
	static Map<String, String> sonFather; //son to father
	static Set<String> visited;
	
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = Integer.parseInt(in.nextLine());
		sonFather = new HashMap<String, String>();
		visited = new HashSet<String>();
		for (int i = 0; i < n; i++) {
			String[] s = in.nextLine().split(" ");
			sonFather.put(s[1], s[0]);
		}
		int m = Integer.parseInt(in.nextLine());
		for (int i = 0; i < m; i++) {
			String[] s = in.nextLine().split(" ");
			quest(s[0],s[1]);
			visited = new HashSet<String>();
		}
		in.close();
	}
	public static void quest(String s1, String s2) {
		if (s1.equals(s2)) {
			System.out.println(s1);
			return;
		}
		if (!sonFather.containsKey(s1) && !sonFather.containsKey(s2)) {
			System.out.println(-1);
			return;
		}
		while (sonFather.containsKey(s1)) {
			visited.add(s1);
			s1 = sonFather.get(s1);
		}
		visited.add(s1);
		while (sonFather.containsKey(s2) && !visited.contains(s2)) {
			s2 = sonFather.get(s2);
		}
		if (visited.contains(s2)) {
			System.out.println(s2);
			return;
		}
		System.out.println(-1);
	}
}