BOJ 25172 꼼꼼한 쿠기의 졸업여행
sorohue가 PS하는 블로그
BOJ 25172 꼼꼼한 쿠기의 졸업여행
문제 링크입니다.
삭제하는 건 싫으니까 합치기에 올인하려 합니다
이상적인 여행 지도는 단일 연결 요소를 이루어야 합니다.
어떤 그래프가 주어졌을 때, 그래프에서 정점을 지워나가면서 그때마다 연결 상태를 판정하는 건 좀 귀찮습니다. 갱신될 만한 값이 많아서…
하지만 그래프에 정점을 추가해 가면서 서로 이어붙이는 건 상대적으로 간단합니다. 분리 집합과 같은 자료 구조를 활용하면 매우 빠르게 작동하기도 하고요.
그래서, 주어진 지울 정점 리스트의 순서를 뒤집어서 합치기를 진행할 겁니다. 하나씩 그래프에 추가하면서, 그 정점과 이어지는 간선 중 이미 그래프에 추가된 정점과 이어지는 간선이 있다면 서로 연결하는 식으로요. 이때 그래프가 단일 연결 요소인지는 새로 추가한 정점이 포함된 연결 요소의 크기가 현재까지 추가한 정점의 개수와 같은지를 보는 것으로 바로 알 수 있습니다. 분리 집합을 구현할 때 집합의 크기를 관리할 수 있게 Union by Size를 써 주면 쉽게 해결할 수 있습니다.
문제 순서를 뒤집어서 풀었으니, 구한 답 역시 반대로 출력해야 함에 유의해 주세요.
코드
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
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
vector<vector<int>> e;
bool vis[234567];
int par[234567];
int F(int x){
return par[x] < 0 ? x : par[x] = F(par[x]);
}
void U(int u, int v){
u = F(u); v = F(v);
if(u == v) return;
if(par[u] < par[v]){
par[u] += par[v];
par[v] = u;
return;
}
par[v] += par[u];
par[u] = v;
return;
}
int main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);
int n, m; cin >> n >> m; e.resize(n+1); while(m--){
int u, v; cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
stack<int> s; for(int i = 1; i <= n; i++){
int x; cin >> x; s.push(x);
}
stack<bool> ss;
memset(par, -1, sizeof(par));
for(int i = 1; i <= n; i++){
int now = s.top(); s.pop();
vis[now] = 1;
for(auto nxt : e[now]) if(vis[nxt]) U(now, nxt);
ss.push(par[F(now)] == -i);
}
while(ss.size()){
cout << (ss.top()?"CONNECT":"DISCONNECT") << '\n';
ss.pop();
}
cout << "DISCONNECT";
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.