티스토리 뷰


문제 제목부터 디스크립션까지 너무 좋은 문제다


문제는 SCC의 기본문제이다

dfs로 풀면 cycle때문에 풀수가없다!


문제를 푸는방법은

1. SCC를 통해 cycle이 없는 그래프로 만든다

2. 각각의 컴포넌트의 indegree를 계산한다

3. indegree가 0인 곳에만 바이러스를 넣어야 최소이다!!


소스코드

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
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
using namespace std;
int n, m, cnt, t, scc_num;
bool check[100010];
int num[100010];
int low[100010];
int sn[100010];
int out[100010];
vector<vector<int>> graph;
vector<vector<int>> ans;
stack<int> st;
 
void dfs(int x) {
    if (check[x]) return;
    check[x] = true;
    num[x] = ++cnt;
    low[x] = cnt;
    st.push(x);
    for (int i = 0; i < graph[x].size(); i++) {
        int y = graph[x][i];
        if (num[y] == 0) {
            dfs(y);
            low[x] = min(low[x], low[y]);
        }
        else if (check[y]) low[x] = min(low[x], num[y]);
    }
 
    if (low[x] == num[x]) {
        vector<int> scc;
        while (!st.empty()) {
            int y = st.top();
            scc.push_back(y);
            check[y] = false;
            st.pop();
            sn[y] = scc_num;
            if (x == y) break;
        }
        ans.push_back(scc);
        scc_num += 1;
    }
}
int main() {
    scanf("%d"&t);
    while (t--) {
        memset(check, 0sizeof(check));
        memset(num, 0sizeof(num));
        memset(low, 0sizeof(low));
        memset(out, 0sizeof(out));
        scc_num = cnt = 0;
        ans.clear();
        graph.clear();
        while (!st.empty()) st.pop();
 
        scanf("%d %d"&n, &m);
        graph.resize(n + 1);
 
        for (int i = 0; i < m; i++) {
            int a, b; scanf("%d %d"&a, &b);
            graph[a].push_back(b);
        }
 
        for (int i = 1; i <= n; i++) {
            if (num[i] == 0) dfs(i);
        }
 
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < graph[i].size(); j++) {
                int next = graph[i][j];
                if (sn[i] != sn[next]) out[sn[next]] += 1;
            }
        }
        int ans = 0;
        for (int i = 0; i < scc_num; i++)
            if (out[i] == 0) ans += 1;
        printf("%d\n", ans);
    }
    return 0;
}
cs


'알고리즘 > BOJ' 카테고리의 다른 글

[백준] 15772 Segmentation  (0) 2018.05.29
[백준] 15803 PLAYERJINAH’S BOTTLEGROUNDS  (0) 2018.05.29
[백준] 14585 사수빈탕  (0) 2018.05.17
[백준] 11581 구호물자  (0) 2018.05.15
[백준] 4256 트리  (0) 2018.05.15
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
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
글 보관함