3977번: 축구 전술
World Soccer Championship이 다가오고 있다! 천재적인 전술을 창조하는 플랜 아티스트 감독 도현이는 자신의 팀이 승리하도록 만반의 준비를 가하고 있다. 도현이의 전략은 경기장을 여러 개의 구역
www.acmicpc.net
강한 연결 요소
1. 문제 해결 아이디어
도미노 문제와 매우 비슷한 문제이다.
<다른 모든 구역에 도달할 수 있는 시작 구역을 찾은 뒤 지시한 움직임만을 따라가라고 했다.> 이 문장을 통해서 SCC임을 알 수 있다.
강한 연결 요소 (SCC) - 타잔 알고리즘
[백준 2150] Strongly Connected Component C++ 2150번: Strongly Connected Component 첫째 줄에 두 정수 V(1 ≤ V ≤ 10,000), E(1 ≤ E ≤ 100,000)가 주어진다. 이는 그래프가 V개의 정점과 E개의 간선으로 이..
hyeo-noo.tistory.com
위 글에서 설명한 타잔 알고리즘을 통해서 문제를 해결했다.
각각의 정점들을 특정한 SCCID를 가진 그룹으로 나눌 수 있고, 나눠진 그룹들은 서로 연결될 수도 있고, 아닐수도 있다.
SCC가 indegree(들어오는 간선)을 가지고 있다면 시작 지점이 될 수 없다.
SCC간의 연결은 양방향 연결이 될 수 없기 때문에(양방향 연결이 된다면 이미 같은 SCC에 포함됨) SCC가 indegree를 가지고 있다면 해당 SCC에서 출발해서는 절대로 모든 SCC를 탐색할 수 없다.
따라서 indegree가 0인 SCC가 2개 이상이라면 (indegree가 0인 SCC들도 서로를 탐색할 수 없기 때문에) 답을 구할 수 없다. (indegree가 0인 SCC가 하나도 없을수는 없다.
2. 코드
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
106
107
108
109
110
111
112
|
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
#define fasti ios_base::sync_with_stdio(false); cin.tie(0);
#define fastio ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define INF 1e9+7
#define pii pair<int, int>
typedef long long ll;
// typedef pair<int, int> pii;
using namespace std;
int N, M;
vector< vector<int> > adj;
int discovered[100001];
int SCCID[100001];
int sccindegree[100001];
int Vcnt;
int SCCcnt;
void init(){
cin >> N >> M;
memset(discovered, -1, sizeof(discovered));
memset(SCCID, -1, sizeof(SCCID));
memset(sccindegree, 0, sizeof(sccindegree));
adj.clear();
adj.resize(N+1, vector<int>());
Vcnt = SCCcnt = 0;
int u, v;
for(int i = 0; i < M; i++){
cin >> u >> v;
adj[u].push_back(v);
}
}
vector<int> stk;
int findSCC(int now){
int ret = discovered[now] = Vcnt++;
stk.push_back(now);
for(auto &next : adj[now]){
if(discovered[next] == -1){
ret = min(ret, findSCC(next));
}
else if(SCCID[next] == -1){
ret = min(ret, discovered[next]);
}
}
if(discovered[now] == ret){
while(true){
int temp = stk.back();
stk.pop_back();
SCCID[temp] = SCCcnt;
if(temp == now) break;
}
SCCcnt++;
}
return ret;
}
void solve(){
for(int i = 0; i < N; i++){
if(discovered[i] != -1) continue;
findSCC(i);
}
for(int i = 0; i < N; i++){
for(auto &w : adj[i]){
if(SCCID[w] == SCCID[i]) continue;
sccindegree[SCCID[w]]++;
}
}
vector<int> temp;
for(int i = 0; i < SCCcnt; i++){
if(!sccindegree[i]){
temp.push_back(i);
}
}
if(temp.size() > 1 || temp.empty()){
cout << "Confused\n";
}
else{
for(int i = 0; i < N; i++){
if(SCCID[i] == temp[0]){
cout << i << "\n";
}
}
}
cout << "\n";
}
int main(){
fasti
int test;
cin >> test;
while(test--){
init();
solve();
}
return 0;
}
|
cs |
'Algorithm > BOJ' 카테고리의 다른 글
[백준 1890] 점프 C++ (0) | 2021.07.21 |
---|---|
[백준 2573] 빙산 C++ (0) | 2021.07.21 |
[백준 1504] 특정한 최단경로 C++ (0) | 2021.07.16 |
[백준 2213] 트리의 독립집합 C++ (2) | 2021.07.15 |
[백준 2458] 키 순서 C++ (0) | 2021.07.14 |