Problem:
D: Walking

問題

$1$ から $N$ の番号がつけられている $N$ 個の島がある.

それぞれの島は $N-1$ 個の橋によって、どの $2$ つの島も何本かの橋を渡って互いに移動することができる.

それぞれの橋には耐久度があり、入力が与えられた時点での $i$ 番目の橋の耐久度は $w_i$ である.

それぞれの島にはお宝が $1$ つずつ置いており、島に滞在しているときにお宝を拾うことができる.

現在島 $S$ にいるyebiくんは、島 $E$ にある博物館に全てのお宝を運びたい.

yebiくんは✝魔力✝を持っているので、島 $v$ に訪問するたびに、 $v$ から出る全ての橋の耐久度が $T$ 減少する.

橋の耐久度が $0$ 以下になったとき、橋は崩壊し、それ以降には渡ることができなくなる.

yebiくんは博物館に全てのお宝を届けることができるか？

ただし、yebiくんは力持ちなので同時にいくつでもお宝を持ち運ぶことができる.

制約

入力値は全て整数である

$2 \leq N \leq 10^5$

$1 \leq S, E \leq N$

$0 \leq T \leq 10^9$

$1 \leq w_i \leq 10^9$

$1 \leq a_i, b_i \leq N$

入力形式

入力は以下の形式で与えられる

$N\ T\ S\ E$

$a_1\ b_1\ w_1$

:

:

$a_{N-1}\ b_{N-1}\ w_{N-1}$

出力

博物館に全てのお宝を届けることができるなら "Yes"、そうでなければ "No" を出力せよ.

また、末尾に改行を出力せよ.

サンプル

サンプル入力 1

4 10 1 4
1 2 52
1 3 68
3 4 45

サンプル出力 1

Yes

サンプル入力 2

4 10 1 4
1 2 15
1 3 60
3 4 10

サンプル出力 2

No

サンプル入力 3

3 0 1 3
1 2 5
2 3 5

サンプル出力 3

Yes

yebiくんの魔力は貧弱すぎて、橋の耐久度を減らすことはできない.

Solution in C (judge verdict: Accepted)

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

int N;
int64_t T;
int S, E;

struct edge_t {
	int to;
	int64_t w;
};

int edgeCounts[114514];
struct edge_t* edges[114514];
int parents[114514];
int parentEdges[114514];

int hasimotokannna(const void* x, const void* y) {
	struct edge_t a = *(const struct edge_t*)x, b = *(const struct edge_t*)y;
	int64_t aa = a.w - T * (edgeCounts[a.to] - 1);
	int64_t bb = b.w - T * (edgeCounts[b.to] - 1);
	return aa < bb ? -1 : aa > bb;
}

void addEdge(int from, int to, int64_t w) {
	int* c = &edgeCounts[from];
	struct edge_t** e = &edges[from];
	struct edge_t* ne = realloc(*e, sizeof(**e) * (*c + 1));
	if (ne == NULL) exit(2);
	ne[*c].to = to;
	ne[*c].w = w;
	(*c)++;
	*e = ne;
}

void dfs(int node, int parent) {
	int i;
	parents[node] = parent;
	for (i = 0; i < edgeCounts[node]; i++) {
		int next = edges[node][i].to;
		if (next != parent) dfs(next, node);
	}
}

int damage[114514];
int got[114514];
int gotCount = 0;

int ikeru(int from, const struct edge_t* edge) {
	return edge->w - T * (damage[from] + damage[edge->to]) > 0;
}

int edgeSinchoku[114514];

int main(void) {
	int i;
	int current;
	if (scanf("%d%" SCNd64 "%d%d", &N, &T, &S, &E) != 4) return 1;
	for (i = 1; i < N; i++) {
		int a, b;
		int64_t w;
		if (scanf("%d%d%" SCNd64, &a, &b, &w) != 3) return 1;
		addEdge(a, b, w);
		addEdge(b, a, w);
	}
	for (i = 1; i <= N; i++) {
		qsort(edges[i], edgeCounts[i], sizeof(edges[i][0]), hasimotokannna);
	}
	dfs(E, 0);
	for (i = 1; i <= N; i++) {
		int j;
		parentEdges[i] = -1;
		for (j = 0; j < edgeCounts[i]; j++) {
			if (edges[i][j].to == parents[i]) parentEdges[i] = j;
		}
	}
	current = S;
	damage[S] = -1;
	for (;;) {
		if (!got[current]) {
			got[current] = 1;
			gotCount++;
		}
		damage[current]++;
		if (gotCount < N) {
			for (;;) {
				if (edgeSinchoku[current] == parentEdges[current]) {
					edgeSinchoku[current]++;
				} else if (edgeSinchoku[current] < edgeCounts[current]) {
					int next = edges[current][edgeSinchoku[current]].to;
					if (got[next]) {
						edgeSinchoku[current]++;
					} else if (ikeru(current, &edges[current][edgeSinchoku[current]])) {
						edgeSinchoku[current]++;
						current = next;
						break;
					} else {
						puts("No");
						return 0;
					}
				} else {
					if (ikeru(current, &edges[current][parentEdges[current]])) {
						current = edges[current][parentEdges[current]].to;
						break;
					} else {
						puts("No");
						return 0;
					}
				}
			}
		} else {
			if (current == E) {
				puts("Yes");
				return 0;
			} else {
				if (ikeru(current, &edges[current][parentEdges[current]])) {
					current = edges[current][parentEdges[current]].to;
				} else {
					puts("No");
					return 0;
				}
			}
		}
	}
}

/*

5 1 1 2
1 3 9999
1 4 2
1 5 9999
1 2 9999

*/

/*

6 1 1 2
1 2 9999
1 3 3
1 4 4
4 5 9999
4 6 9999

*/