算法笔记_146:TarJan算法的应用(Java)
目录
1 问题描述
Problem Description
为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以通过这个通道由A房间到达B房间,但并不说明通过它可以由B房间到达A房间。Gardon需要请你写个程序确认一下是否任意两个房间都是相互连通的,即:对于任意的i和j,至少存在一条路径可以从房间i到房间j,也存在一条路径可以从房间j到房间i。
Input
输入包含多组数据,输入的第一行有两个数:N和M,接下来的M行每行有两个数a和b,表示了一条通道可以从A房间来到B房间。文件最后以两个0结束。
Output
对于输入的每组数据,如果任意两个房间都是相互连接的,输出"Yes",否则输出"No"。
Sample Input
3 3 1 2 2 3 3 1 3 3 1 2 2 3 3 2 0 0
Sample Output
Yes No
2 解决方案
具体代码如下:
package com.liuzhen.practice; import java.util.ArrayList; import java.util.Scanner; import java.util.Stack; public class Main { public static int n; //给定图的顶点数 public static int count; public static int[] DFN; public static int[] Low; public static int[] inStack; public static ArrayList<edge>[] map; public static Stack<Integer> stack; public static ArrayList<String> result = new ArrayList<String>(); static class edge { public int a; public int b; public edge(int a, int b) { this.a = a; this.b = b; } } @SuppressWarnings("unchecked") public void init() { count = 1; DFN = new int[n + 1]; Low = new int[n + 1]; inStack = new int[n + 1]; map = new ArrayList[n + 1]; stack = new Stack<Integer>(); for(int i = 1;i <= n;i++) { DFN[i] = -1; Low[i] = -1; inStack[i] = -1; map[i] = new ArrayList<edge>(); } } public boolean TarJan(int start) { DFN[start] = count++; Low[start] = DFN[start]; inStack[start] = start; stack.push(start); int j = start; for(int i = 0;i < map[start].size();i++) { j = map[start].get(i).b; if(DFN[j] == -1) { TarJan(j); Low[start] = Math.min(Low[start], Low[j]); } else if(inStack[j] != -1) { Low[start] = Math.min(Low[start], DFN[j]); } } if(DFN[start] == Low[start]) { int num = 0; do { j = stack.pop(); num++; } while(j != start); if(num == DFN.length - 1) return true; } return false; } public static void main(String[] args) { Main test = new Main(); Scanner in = new Scanner(System.in); while(true) { n = in.nextInt(); //图中顶点数 int k = in.nextInt(); // 图中边数 if(n == 0 || k == 0) break; test.init(); int start = 1; for(int i = 0;i < k;i++) { int a = in.nextInt(); int b = in.nextInt(); map[a].add(new edge(a, b)); start = a; } if(test.TarJan(start)) result.add("Yes"); else result.add("No"); } for(int i = 0;i < result.size();i++) { System.out.println(result.get(i)); } } }
运行结果:
3 3
1 2
2 3
3 1
3 3
1 2
2 3
3 2
0 0
Yes
No
参考资料:
每天一小步,成就一大步