You will be fine

<Algorithm> 63. 11266번 단절점

by BFine
반응형

11266번 단절점

  • DFS Spanning Tree 알고리즘과 그에 대한 활용할 수 있는 지에 대한 문제  
  • 단절점의 특징을 이해하는데 다소 시간이 많이 걸렸다. 처음에는 단순히 DFS로 모든 경우를 탐색했는데 시간초과가 발생했다.
  • Spanning Tree는 순서와 루트 체크를 위해 필요했고 기존 그래프를 계속 사용되는 것을 생각해주어야 한다.
  • Spanning Tree로 탐색하면서 방문한 정점의 인접 정점 중 하나라도 방문한 정점의 이전 순서의 정점로 갈 수 있을 경우 단절점아니다. 
  • 이때 이전순서는 Spanning Tree로 탐색하는 경우가 되고 이전순서로 가는 것을 확인하는 경우는 기존 그래프를 이용해야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
 
public class Main {
    static int count = 1;
    
    static int[] discovered;
    static boolean[] isCutVertax;
    
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken())+1;
        int M = Integer.parseInt(st.nextToken());
        ArrayList<Node>[] aLists = new ArrayList[N];
        
        discovered = new int[N];
        isCutVertax = new boolean[N];
        
        for(int i = 0; i < N; i ++) {
            aLists[i] = new ArrayList<>();
        }
        
        for(int i = 0; i < M; i ++) {
            st = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            aLists[a].add(new Node(b));
            aLists[b].add(new Node(a));
        }
        
        for(int i = 1; i < N ;i ++) {
            if(discovered[i] == 0) {
                dfs(i, true, aLists);
            }
        }
        int cnt = 0;
        for(int i = 1; i < N ; i++) {
            if(isCutVertax[i]) {
                cnt++;
            }
        }
        System.out.println(cnt);
        for(int i = 1; i < N ; i++) {
            if(isCutVertax[i]) {
                System.out.print(i +" ");
            }
        }
        
    }
    private static int dfs(int vertax, boolean root, ArrayList<Node>[] aLists) {
        /* 자기보다 앞에 탐색할수 있는 경우가 있으면 단절점이 되지 않는다. */
        /* DFS스패닝트리를 만들면서 기존 트리는 그대로 사용됨 없어지는 것이 아님*/
        /* DFS스패닝 트리의 역할은 순서를 지정해 주는 것과 
         * DFS스패닝 트리에서 루트가 자식을 2개 가지는지 체크 */
        
        
        discovered[vertax] = count++;
        int ret = discovered[vertax];
        // 자기랑 인접노드 중에서 가장 빨리 방문되는 노드의 순서를 저장하는 변수
        
        int child = 0// 루트 노드일 경우 스패닝트리에서 자식수
                
        for(Node no: aLists[vertax]) {
            if(discovered[no.adjVertax] == 0) {
                child ++;
                
                int low = dfs(no.adjVertax, false, aLists);
                // 자식 노드가 갈수 있는 노드중 가장 일찍 방문한 노드
                // 중간에 dfs 한다는 것은 정점의 끝까지 간다는 것을 의미
                
                if(!root && low >= discovered[vertax]) {
                    isCutVertax[vertax] = true;
                }// low가 자기의 순서보다 늦거나 같은 경우는 
                //즉 자기보다 앞에 있는 경로는 자기를 통해서 밖에 못간다. 단절점
 
                
                ret = Math.min(ret, low);
            }else {
                ret = Math.min(ret, discovered[no.adjVertax]);
                // 이미 방문한 정점과 ret값 비교 최소값 저장
            }
        }
        
        if(root && child >= 2) {
            isCutVertax[vertax] = true;
        }// 루트는 위의 방법으로 확인할 수가 없기 때문에 스패닝 트리에서
         // 자식이 두개 있다는 것은 단절점이다.
        
        return ret;
    }// dfs에서 다른 노드 값을 얻고 싶을때 return 아래에 사용
    
}
class Node{
    int adjVertax;
    public Node(int adjVertax) {
        super();
        this.adjVertax = adjVertax;
    }
}    
 
 
cs

 

 

출처 : http://bowbowbow.tistory.com/3, http://jason9319.tistory.com/119

반응형

블로그의 정보

57개월 BackEnd

BFine

활동하기