提出 #52108472


ソースコード 拡げる

Copy
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
struct edge_s {
int to, id, rev_id;
};
int ec[114514];
struct edge_s *es[114514];
void ae(int f, int t, int id, int rev_id) {
es[f] = realloc(es[f], sizeof(*es[f]) * (ec[f] + 1));
if (es[f] == NULL) exit(2);
es[f][ec[f]].to = t;
es[f][ec[f]].id = id;
es[f][ec[f]].rev_id = rev_id;
ec[f]++;
}
int N;
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

struct edge_s {
	int to, id, rev_id;
};

int ec[114514];
struct edge_s *es[114514];

void ae(int f, int t, int id, int rev_id) {
	es[f] = realloc(es[f], sizeof(*es[f]) * (ec[f] + 1));
	if (es[f] == NULL) exit(2);
	es[f][ec[f]].to = t;
	es[f][ec[f]].id = id;
	es[f][ec[f]].rev_id = rev_id;
	ec[f]++;
}

int N;
int A[114514], B[114514];
int C[114514];

struct meow_s {
	uint64_t f_value;
	uint64_t sum_of_C;
};

struct meow_s memo[114514];
char memo_status[114514];
struct meow_s delta_cache[114514 * 2];
struct edge_s memo_tarinai[114514];

struct meow_s calc(int node, int from_edge_id) {
	struct meow_s ret = {0, 0};
	int i;
	if (memo_status[node] == 0) {
		/* メモが全く無い */
		for (i = 0; i < ec[node]; i++) {
			if (es[node][i].rev_id == from_edge_id) {
				memo_tarinai[node] = es[node][i];
			} else {
				struct meow_s delta = calc(es[node][i].to, es[node][i].id);
				/* 下層の分を足し、さらに上がったので C_i の合計を足す */
				ret.f_value += delta.f_value + delta.sum_of_C;
				/* 新しい C_i の合計を求める */
				ret.sum_of_C += delta.sum_of_C;
				/* キャッシュする */
				delta_cache[es[node][i].rev_id] = delta;
			}
		}
		ret.sum_of_C += C[node];
		memo[node] = ret;
		memo_status[node] = from_edge_id < 0 ? 2 : 1;
		return ret; /* 分岐で抜いているので、来た辺の分のロールバックは不要 */
	}
	if (memo_status[node] == 1) {
		/* 欠けている場所がある */
		if (memo_tarinai[node].rev_id == from_edge_id) {
			/* 同じ場所が欠けている */
			return memo[node];
		} else {
			/* 違う場所が欠ける → 埋めることができる */
			struct meow_s delta = calc(memo_tarinai[node].to, memo_tarinai[node].id);
			/* 下層の分を足し、さらに上がったので C_i の合計を足す */
			memo[node].f_value += delta.f_value + delta.sum_of_C;
			/* 新しい C_i の合計を求める */
			memo[node].sum_of_C += delta.sum_of_C;
			/* キャッシュする */
			delta_cache[memo_tarinai[node].rev_id] = delta;
			/* 欠けが解消したことを記録する */
			memo_status[node] = 2;
			/* 下のロールバックの処理に行く */
		}
	}
	ret = memo[node];
	if (from_edge_id >= 0) {
		/* 来た辺の分をロールバック */
		ret.f_value -= delta_cache[from_edge_id].f_value + delta_cache[from_edge_id].sum_of_C;
		ret.sum_of_C -= delta_cache[from_edge_id].sum_of_C;
	}
	return ret;
}

int main(void) {
	int i;
	uint64_t ans;
	if (scanf("%d", &N) != 1) return 1;
	for (i = 1; i < N; i++) {
		if (scanf("%d%d", &A[i], &B[i]) != 2) return 1;
		ae(A[i], B[i], 2 * (i - 1), 2 * (i - 1) + 1);
		ae(B[i], A[i], 2 * (i - 1) + 1, 2 * (i - 1));
	}
	for (i = 1; i <= N; i++) {
		if (scanf("%d", &C[i]) != 1) return 1;
	}
	ans = calc(1, -1).f_value;
	for (i = 2; i <= N; i++) {
		uint64_t candidate = calc(i, -1).f_value;
		if (candidate < ans) ans = candidate;
	}
	printf("%" PRIu64 "\n", ans);
	return 0;
}

/*

f(x) = (C_i × そこに行くまでのステップ数) の合計
これをサブツリーについて計算する
単純に C_i の和 → これを1段深くなるごとに加える

*/

提出情報

提出日時
問題 E - Minimize Sum of Distances
ユーザ mikecat
言語 C (gcc 12.2.0)
得点 475
コード長 3298 Byte
結果 AC
実行時間 54 ms
メモリ 20676 KB

ジャッジ結果

セット名 Sample All
得点 / 配点 0 / 0 475 / 475
結果
AC × 3
AC × 31
セット名 テストケース
Sample example0.txt, example1.txt, example2.txt
All example0.txt, example1.txt, example2.txt, test_00.txt, test_01.txt, test_02.txt, test_03.txt, test_04.txt, test_05.txt, test_06.txt, test_07.txt, test_08.txt, test_09.txt, test_10.txt, test_11.txt, test_12.txt, test_13.txt, test_14.txt, test_15.txt, test_16.txt, test_17.txt, test_18.txt, test_19.txt, test_20.txt, test_21.txt, test_22.txt, test_23.txt, test_24.txt, test_25.txt, test_26.txt, test_27.txt
ケース名 結果 実行時間 メモリ
example0.txt AC 1 ms 1620 KB
example1.txt AC 1 ms 1660 KB
example2.txt AC 0 ms 1664 KB
test_00.txt AC 28 ms 9352 KB
test_01.txt AC 18 ms 6728 KB
test_02.txt AC 33 ms 10680 KB
test_03.txt AC 7 ms 4184 KB
test_04.txt AC 27 ms 11008 KB
test_05.txt AC 15 ms 7232 KB
test_06.txt AC 20 ms 9264 KB
test_07.txt AC 19 ms 9696 KB
test_08.txt AC 15 ms 7284 KB
test_09.txt AC 47 ms 13820 KB
test_10.txt AC 40 ms 13820 KB
test_11.txt AC 47 ms 13812 KB
test_12.txt AC 40 ms 13680 KB
test_13.txt AC 48 ms 13808 KB
test_14.txt AC 41 ms 13804 KB
test_15.txt AC 36 ms 14384 KB
test_16.txt AC 30 ms 14272 KB
test_17.txt AC 35 ms 14384 KB
test_18.txt AC 30 ms 14260 KB
test_19.txt AC 37 ms 14380 KB
test_20.txt AC 30 ms 14372 KB
test_21.txt AC 54 ms 20564 KB
test_22.txt AC 44 ms 20676 KB
test_23.txt AC 52 ms 18748 KB
test_24.txt AC 44 ms 18004 KB
test_25.txt AC 50 ms 19152 KB
test_26.txt AC 44 ms 19628 KB
test_27.txt AC 0 ms 1672 KB


2024-04-07 (日)
22:10:16 +00:00