조건


1. 1번 방이 루트

2. 굴의 길이만큼 에너지가 소모된다

3. 불필요한 굴은 짓지 않는다 -> 각 방에서 루트까지 가는 경로는 유일하다

4. 방마다 개미는 하나만 있다.


해결법


1. dfs를 돌리는데 현재 위치까지의 경로 길이의 누적합을 저장한다.

ex) 1 - 2 - 3 - 4   로 이어지고 코스트가 각각 3,9,6이라고 한다면

     0   3   12  18 가 저장된다


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
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
 
const int MV = 100000;
typedef pair<intint> pii;
 
int n, depth, visited = 2e9;
int a[MV + 1], d[MV + 1], l[MV + 1], l2[MV + 1], s[MV + 1];
vector<pii> adj[MV + 1];
 
int bs(int x) {
    int le = 0, ri = depth, t = l[depth] - a[x], ans = depth;
    while (le <= ri) {
        int mid = (le + ri) / 2;
        if (l[mid] >= t) {
            ri = mid - 1;
            ans = mid;
        }
        else le = mid + 1;
    }
    return ans;
}
 
void dfs(int x) {
    s[x] = a[x] >= l[depth] ? 1 : l2[bs(x)];
    for (auto i : adj[x]) {
        if (d[i.first] != visited) continue;
        int nx = i.first, c = i.second;
        d[nx] = d[x] + c;
        l[++depth] = d[nx]; l2[depth] = nx;
 
        dfs(nx);
 
        l2[depth] = 0; l[depth--= 0;
    }
}
 
int main() {
    scanf("%d"&n);
    for (int i = 1; i <= n; i++scanf("%d"&a[i]);
    for (int i = 0; i < n - 1; i++) {
        int u, v, w; 
        scanf("%d%d%d"&u, &v, &w);
        adj[u].push_back({ v,w });
        adj[v].push_back({ u,w });
    }
    fill(d, d + n + 12e9);
    d[1= 0; l2[0= 1;
    dfs(1);
    for (int i = 1; i <= n; i++printf("%d\n", s[i]);
    return 0;
}
cs


'BOJ' 카테고리의 다른 글

3986 좋은 단어  (0) 2018.02.17
14941 호기심  (0) 2018.02.17
15270 친구 팰린드롬  (0) 2018.02.17
15271 친구 팰린드롬 2  (0) 2018.02.17
15312 이름 궁합  (0) 2018.02.17

+ Recent posts