<네이버에서 옮겨온 것>
한줄 후기 : 처음이자 마지막(?) 본선
https://www.acmicpc.net/problem/19542
전단지 돌리기 성공출처
Gold IV
깊이 우선 탐색그래프 이론그래프 탐색트리
난이도 제공: solved.ac — 난이도 투표하러 가기
시간 제한 |
메모리 제한 |
제출 |
정답 |
맞은 사람 |
정답 비율 |
1 초 (추가 시간 없음) |
1024 MB |
381 |
182 |
162 |
51.266% |
문제
현민이는 트리 모양의 길 위에서 오토바이를 타고 전단지를 돌리려고 한다. 현민이의 목표는 케니소프트에서 출발하여 모든 노드에 전단지를 돌리고, 다시 케니소프트로 돌아오는 것이다. 현민이는 힘이 좋기 때문에 현재 노드에서 거리가
D이하인 모든 노드에 전단지를 돌릴 수 있다.
날씨가 매우 덥기 때문에, 현민이는 최소한만 이동해서 목표를 달성하고 싶다! 현민이를 위해 현민이가 이동해야 하는 총 거리를 구해주자.
입력
첫번째 줄에는 노드의 개수 N(1≤N≤100 000)과 케니소프트의 위치 S(1≤S≤N), 힘 D(0≤D≤N)이 주어진다.두 번째 줄부터 N번째 줄까지, 트리의 간선 정보를 의미하는 두 자연수 x, y가 공백으로 구분되어 주어진다. 이는 x번 노드와 y번 노드가 연결되어 있음을 의미한다. (1≤x,y≤N, x≠y)
주어지는 연결관계는 트리를 구성하며, 모든 간선의 길이는 1이다.
출력
현민이가 목표를 완수하기 위해 이동해야 하는 최소 거리를 출력하여라.
예제 입력 1
6 1 1 1 2 2 3 2 4 3 5 5 6 |
예제 출력 1
6 |
출처
Contest > 전국 대학생 프로그래밍 대회 동아리 연합 여름 대회 > UCPC 2020 A번
애증의 UCPC 본선 문제..
우리팀에선 지혜랑 나랑 풀었다. + 다른팀에서는 하얀이가
처음에 보자마자 dfs네 하고 내가 코드를 짰다가 틀렸는데 바보같이 자식 개수로 갈지 안갈지를 비교했다. 이건 그런게 아니라 현재 위치에서 자식 전체의 깊이를 비교해야 하는 문제다.
그래서 그걸 어떻게 할 지 고민하다. 그래프 탐색을 2번 하는 것으로 방향을 잡고 풀었다.
1번째 DFS에서는 재귀로 돌면서 재귀가 끝날 때마다 즉, 거꾸로 올라가면서 내 뒤에 노드의 깊이를 저장해줬다. 2번 BFS 에서는 전체 탐색하면서 전단지를 어디까지 돌릴지 거리를 계산했다.
참고로 돌아올 때는 결국 똑같이 돌아올 거니 *2해주면 된다. 생각보다 심플한 문제인데 노드 10만개를 보고 탐색 2번이라 시간초과는 안날지, 거꾸로 깊이 저장을 어떻게 할지 우리가 너무 고민했다. 생각해보면 시간초과는 절대 안나는데 ㅋㅋㅋㅋㅋㅋㅋ
BFS와 DFS의 인접리스트 시간복잡도가 O(V+E)이니 두번을 동시에 돌린게 아니라 시간초과는 걱정 안해도 된다.
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
vector<int> node[100001];
int a[100001];
bool visit[100001];
int n, s, d;
int dfs(int x) {
int depth=0;
bool leaf = true;
visit[x] = true;
for (int i = 0; i < node[x].size(); i++) {
int y = node[x][i];
if (!visit[y]) {
leaf = false;
depth = max(depth, dfs(y) + 1);
}
}
if (!leaf)
a[x] = depth;
return a[x];
}
int main() {
scanf("%d %d %d", &n, &s, &d);
for (int i = 1; i < n; i++) {
int x, y;
scanf("%d %d", &x, &y);
node[x].push_back(y);
node[y].push_back(x);
}
for (int i = 1; i <= n; i++)
visit[i] = false;
dfs(s);
int ans = 0;
queue<int> q;
q.push(s);
for (int i = 1; i <= n; i++)
visit[i] = false;
visit[s] = true;
if (a[s] > d) {
while (!q.empty()) {
int x = q.front();
q.pop();
for (int i = 0; i < node[x].size(); i++) {
int y = node[x][i];
if (!visit[y] && a[y] >= d) {
q.push(y);
visit[y] = true;
ans++;
}
}
}
}
printf("%d\n", ans * 2);
}
다른 후기들을 보니 BFS 한번에 구현한 팀도 있다더라 정말 대단해 나도 코드를 효율적으로 짜고 싶다 ㅋ..
'DEV > PS' 카테고리의 다른 글
[1699] 제곱수의 합, c++ (0) | 2021.02.06 |
---|---|
[1039] 중량 제한, c++ (0) | 2021.02.06 |
[5582] 공통 부분 문자열, c++ (0) | 2021.02.04 |
[6448] Stockbroker Grapevine, c++ (0) | 2021.02.04 |
[1197] 최소 스패닝 트리, c++ (0) | 2021.02.04 |