1976번: 여행 가자
동혁이는 친구들과 함께 여행을 가려고 한다. 한국에는 도시가 N개 있고 임의의 두 도시 사이에 길이 있을 수도, 없을 수도 있다. 동혁이의 여행 일정이 주어졌을 때, 이 여행 경로가 가능한 것인
www.acmicpc.net
도시의 수가 주어지고 인접 행렬이 반사 행렬로 주어지니 무향 그래프로 봐도 된다.
이후 여행 갈 도시의 동선이 주어지는데 이를 path 배열로 받아줬다.
처음에는 DFS로 접근해서
void DFS(int cur) {
vis[cur] = true;
for (int i = 1; i <= n; i++) {
if (ar[i] && !vis[i]) {
DFS(i);
}
}
}
이런 식으로 방문하지 않았다면 DFS를 돌리는 식으로 해줬는데
in:
5
2
0 1 1 0 0
1 0 0 0 0
1 0 0 0 0
0 0 0 0 1
0 0 0 1 0
1 5
out:
NO
이런 식의 반례가 존재했다.
즉 모든 경우에 대해 DFS를 돌리기 때문에 vis배열에서도 모두 true로 나오게 되고 같은 컴포넌트인지 구분할 수 없었다.
이 부분은 따로 처리해주면 되겠지만 유니온 파인드를 배운 겸 유니온 파인드로 풀었다.
- n * n 만큼 입력을 받으면서 입력받은 값이 1 이면 i -> j를 union 해준다
- 이후 path 배열을 입력받고 path[0] 의 루트 노드를 찾는다
- path 배열을 돌면서 path[0] 의 루트 노드와 다르다면 갈 수 없는 동선이니 NO
- 아니라면 YES를 출력해준다
#include <iostream>
using namespace std;
int parent[1001], path[1001];
int find(int x) {
if (parent[x] == x) return x;
return parent[x] = find(parent[x]);
}
void merge(int x, int y) {
x = find(x);
y = find(y);
if (x != y) parent[y] = x;
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
int n, m, x;
cin >> n >> m;
for (int i = 0; i <= n; i++) {
parent[i] = i;
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin >> x;
if (x) merge(i, j);
}
}
for (int i = 0; i < m; i++) cin >> path[i];
int root = find(path[0]);
for (int i = 0; i < m; i++) {
if (root != find(path[i])) {
cout << "NO" << endl; return 0;
}
}
cout << "YES" << endl;
return 0;
}
'BOJ' 카테고리의 다른 글
BOJ 1932 정수 삼각형 (0) | 2020.10.22 |
---|---|
BOJ 4195 친구 네트워크 (0) | 2020.10.17 |
BOJ 2470 두 용액 (0) | 2020.10.11 |
BOJ 7795 먹을 것인가 먹힐 것인가 (0) | 2020.10.11 |
BOJ 1806 부분합 (0) | 2020.10.10 |