반응형
    
    
    
  https://www.acmicpc.net/problem/6543
6543번: 그래프의 싱크
각 테스트 케이스마다 한 줄에 걸쳐 bottom(G)의 모든 노드를 출력한다. 노드는 공백으로 구분해야 하며, 오름차순이어야 한다. 만약, bottom(G)가 공집합이면 빈 줄을 출력한다.
www.acmicpc.net

SCC를 찾는 문제인데 간선이 존재하지 않는 노드는 그자체가 강한 연결요소이다.
위의 그림처럼 5번을 제외한 나머지 노드들은 강한 연결요소가 아니다 1->2->3 은 강한 연결요소인것 같지만
3->4 edge도 존재하기 때문에 강한 연결 요소가 아니다 이러한 경우의 SCC는 제외하면 된다.
SCC를 만들어가는 과정에서 현재 사이클에서 SCC가 만들어진 집단에대해서 연결된 edge가 false가 존재한다는 것은 outline이 한개 더 존재한다는 것이다. 이때의 SCC 집단은 무효화하는 함수를 추가한다.
정렬해서 출력한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Stack;
import java.util.StringTokenizer;
public class B6543 {
	static int V, E;
	static ArrayList<Integer> graph[];
	static ArrayList<Integer> reGraph[];
	static Stack<Integer> stack;
	static boolean visit[];
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		StringBuilder sb = new StringBuilder();
		while (true) {
			st = new StringTokenizer(br.readLine());
			if ((V = Integer.parseInt(st.nextToken())) == 0)
				break;
			E = Integer.parseInt(st.nextToken());
			// Size Init
			graph = new ArrayList[V + 1];
			reGraph = new ArrayList[V + 1];
			visit = new boolean[V + 1];
			for (int v = 1; v <= V; v++) {
				graph[v] = new ArrayList<Integer>();
				reGraph[v] = new ArrayList<Integer>();
			}
			st = new StringTokenizer(br.readLine());
			for (int e = 0; e < E; e++) {
				int u = Integer.parseInt(st.nextToken());
				int v = Integer.parseInt(st.nextToken());
				graph[u].add(v);
				reGraph[v].add(u);
			}
			stack = new Stack<>();
			for (int v = 1; v <= V; v++) {
				if (!visit[v])
					dfs(v);
			}
			ArrayList<Integer> list = new ArrayList<Integer>();
			Arrays.fill(visit, false);
			while (!stack.isEmpty()) {
				int node = stack.pop();
				if (!visit[node]) {
					int t = list.size();
					SCC(node, list);
					boolean check = true;
					for (int i = t; i < list.size(); i++) {
						int len = graph[list.get(i)].size();
						for (int j = 0; j < len; j++) {
							// 하나라도 다른게 존재한다면 지금 추가된 SCC 모드는 제거하겠다.
							if (!visit[graph[list.get(i)].get(j)]) {
								check = false;
								break;
							}
						}
						if (!check)
							break;
					}
					
					// 현재 템포에서 추가된 SCC를 제거하는 코드
					if (!check) {
						while (list.size() > t) {
							list.remove(list.size() - 1);
						}
					}
				}
			}
			Collections.sort(list);
			for (int l : list) {
				sb.append(l).append(' ');
			}
			sb.append('\n');
		}
		System.out.println(sb.toString());
	}
	static void dfs(int node) {
		visit[node] = true;
		for (int next : graph[node]) {
			if (!visit[next]) {
				dfs(next);
			}
		}
		stack.add(node);
	}
	// stack에 나온걸 가지고 찾는 dfs
	public static void SCC(int node, ArrayList<Integer> list) {
		visit[node] = true;
		list.add(node);
		for (int next : reGraph[node]) {
			if (!visit[next]) {
				SCC(next, list);
			}
		}
	}
}
반응형
    
    
    
  'ProgramSoliving' 카테고리의 다른 글
| 백준 : 14725 (트라이) (0) | 2020.07.18 | 
|---|---|
| 백준 : 10266 (0) | 2020.07.18 | 
| 백준 : 6497 (0) | 2020.07.14 | 
| 백준 : 11585 속터지는 저녁 메뉴 (0) | 2020.07.13 | 
| 백준 : 1305 (광고) java (0) | 2020.07.13 |