일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 그리디
- 백준
- lis
- 펜윅트리
- 삼분탐색
- 누적합
- 이분매칭
- 이분탐색
- dfs
- BFS
- 에라토스테네스의 체
- 이진탐색
- DP
- MST
- 세그먼트트리
- 투포인터
- lca
- 수학
- 크루스칼
- 플로이드와샬
- 다익스트라
- 브루트포스
- LazyPropagation
- DisjointSet
- 좌표압축
- 구현
- 정렬
- 비트마스크
- 위상정렬
- boj
Archives
- Today
- Total
lastknight00
[백준]개미(14942) 본문
문제 링크 : [백준]개미(14942)
문제 설명
트리가 주어지고, 각 노드간의 거리가 주어집니다.
그때 각 노드별로 루트 노드를 향해 이동할 수 있는 비용이 주어집니다.
각 노드별로 루트에 가장 가깝게 갈 수 있는 노드의 번호를 출력하세요.
입력
N(노드의 갯수, 1 <= N <= 100,000)
Ei(노드별로 이동 할 수 있는 거리, 1 <= Ei <= 100,000)
Dai Dbi Dci(노드 간 연결 정보, Dai, Dbi 두 노드간 거리가 Dci 입니다. 1 <= Dci <= 10,000)
4
10
8
22
18
1 2 10
2 3 10
2 4 10
출력
1
2
1
2
카테고리
#누적합 #DFS #이분탐색
시간 복잡도 상한
O(NlogN)
해결 방법
- DFS로 1번 노드(Root)에서 각 노드를 방문하며, 각 노드가 가진 비용만큼 위로 올라가면서 자신이 가진 비용보다 커지는 위치를 찾으며 답을 구하면 됩니다.
- 그러나 최악의 경우 O(N2)이 되어 TLE가 됩니다.
- 특정 노드에서 루트까지의 거리를 빠르게 구할 수 있다면 풀 수 있을 것 같습니다.
- 각 노드를 기준으로, 자신의 부모 노드들까지의 거리를 알 수 있다면, upper_bound를 이용하여, O(logN)만에 각 노드에서 갈 수 있는 노드를 찾을 수 있습니다. 최종적으로 O(NlogN)에 해결 할 수 있습니다.
- 한 노드에서 모든 부모노드까지의 거리를 구하려면 N2이 걸릴 것입니다.
- DFS를 이용하면 단말 노드까지 오면서 자신의 부모에 대한 정보들을 유지하면서 올 수 있다는 점을 이용합니다.
- 단말노드까지 오면서 거쳐온 정보들을 유지하면서, 단말노드에 도착하면, 단말노드를 기준으로 루트노드까지의 거리의 누적합들을 구합니다.
- DFS에서 거꾸로 올라가면서, 단말노드에서 자신까지 오는 거리 + 자신이 갈 수 있는 거리를 가지고 upper_bound를 이용하여 자신이 갈 수 있는 부모 노드를 구합니다.
시간복잡도
O(NlogN)
코드
#include<iostream>
#include<algorithm>
#include<vector>
#include<deque>
#define M 100001
using namespace std;
typedef pair<int,int> P;
int n,d[M],a[M],i,x,y,z;
vector<P>v[M],w;
deque<int>d1,d2;
void r(int x,int u){
int t=1;
for(P k:v[x]){
if(k.second==u)continue;
t=0;
w.push_back({k.first,x});
r(k.second,x);
w.pop_back();
}
if(t){
d1.clear();d2.clear();
d1.push_back(0);
d2.push_back(x);
for(int i=w.size()-1;i>=0;i--){
d1.push_back(d1.back()+w[i].first);
d2.push_back(w[i].second);
}
a[x]=d2[upper_bound(d1.begin(),d1.end(),d[x])-d1.begin()-1];
d1.pop_front();d2.pop_front();
}else{
int c=d[x]+d1.front();
d1.pop_front();d2.pop_front();
if(d1[0]>c)a[x]=x;
else a[x]=d2[upper_bound(d1.begin(),d1.end(),c)-d1.begin()-1];
}
}
int main(){
ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n;
for(i=1;i<=n;i++)cin>>d[i];
for(i=1;i<n;i++){
cin>>x>>y>>z;
v[x].push_back({z,y});
v[y].push_back({z,x});
}
r(1,0);
for(i=1;i<=n;i++)cout<<a[i]<<"\n";
}
'PS' 카테고리의 다른 글
[백준]리유나는 세일러복을 좋아해(18138) (0) | 2020.07.04 |
---|---|
[백준]배열과 연산(14222) (0) | 2020.07.04 |
[백준]교수님은 기다리지 않는다(3830) (0) | 2020.06.29 |
[백준]피리 부는 사나이(16724) (0) | 2020.06.29 |
[백준]전구 끄기(14927) (0) | 2020.06.29 |
Comments