B 小琛和他的学校

链接:https://ac.nowcoder.com/acm/contest/4047/B
来源:牛客网

题目描述
小琛是一所学校的校长。
他的学校有n个校区(编号1~n),被n-1条双向道路连接,呈树形结构。
第i个校区共有Ai个学生。
第i天早上,所有的学生会沿最短路走到第i个校区参加活动,晚上再原路返回。
一个人通过第j条通道一次(即一人次),需要小琛支付wj的维护费用。
小琛想知道第n天结束之后,对于每一条通道,他总共需要支付多少费用。
对于100%的数据,1≤ n ≤ 200,000,1≤ A[i]≤ 10,000,1≤ w[i] ≤ 10,000。
输入描述:

第一行一个整数n,表示校区的数量。
接下来一行,n个整数,表示A1~An。
第3到第n+1行,每行包含3个整数。第i行包含三个整数ui-2,vi-2,wi-2,表示第i-2条通道所连接的两个校区的编号,以及一人次通过这条通道的费用。

输出描述:

共n-1行,每行一个整数。
第i行的整数表示小琛对于第i条通道所需支付的费用。

示例1
输入
复制

4
2 1 2 3
1 3 1
1 2 3
4 1 2

输出
复制

24
60
56

利用dfs的回溯来进行一些操作,和Tarjan有点类似。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;

const int maxn = 2e5 + 10;
typedef long long ll;
struct node{
	int u, v, nex, id, cost;
}edge[maxn * 2];
ll n, ans[maxn];
int head[maxn];
ll a[maxn], cnt, tot, maxSum;
ll sz[maxn], sum[maxn];

void addedge(int u, int v, int id, int cost) {
	edge[cnt] = {u, v, head[u], id, cost};
	head[u] = cnt++;
}

void init() {
	memset(head, -1, sizeof(head));
}

void dfs(int u, int fa) {
	sz[u] = 1;
	sum[u] = a[u];
	for(int i = head[u]; i != -1; i = edge[i].nex) {
		int v = edge[i].v;
		if(v == fa)
			continue;
		dfs(v, u);
		sum[u] += sum[v];
		sz[u] += sz[v];
		int id = edge[i].id;
		ans[id] = (sz[v] * (maxSum - sum[v]) + (n - sz[v]) * sum[v]) * edge[i].cost;
	}
}

int main() {
	init();
	ios::sync_with_stdio(false);
	cin >> n;
	for(int i = 1; i <= n; i++) {
		cin >> a[i];
		maxSum += a[i];
	}
	for(int i = 1; i < n; i++) {
		int u, v, data;
		cin >> u >> v >> data;
		addedge(u, v, i, data);
		addedge(v, u, i, data);
	}
	dfs(1, 0);
	for(int i = 1; i < n; i++)
		cout << ans[i] * 2 << endl;
	return 0;
}
发布了78 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ln2037/article/details/104005107
B
今日推荐