40pts求调
查看原帖
40pts求调
605226
modfisher楼主2023/10/4 21:02
#include <bits/stdc++.h>

using namespace std;

const int maxn = 2e5 + 5;

vector<int> G[maxn];
int n, T;
long long a[maxn], w[maxn], sum[maxn];
long long dep[maxn], siz[maxn], dss[maxn], maxd = 0;

bool cmp(int x, int y){
	return sum[y] * siz[x] < sum[x] * siz[y];
}
void dfs(int x, int f){
	if(x != 1) dep[x] = dep[f] + 1;
	siz[x] = 1;
	sum[x] = a[x];
	for(int i = 0; i < G[x].size(); i ++){
		int j = G[x][i];
		dfs(j, x);
		siz[x] += siz[j];
		sum[x] += sum[j];
	}
	if(T == 0) return;
	if(siz[x] == 1){
		dss[x] = dep[x];
	}
	if(dss[x] > dss[f]){
		dss[f] = dss[x];
	}
	maxd = max(maxd, dep[x]);
}
void dfs2(int x, bool fl){
	sort(G[x].begin(), G[x].end(), cmp);
	int ds;
	if(siz[x] > 0){
		for(int i = G[x].size() - 1; i >= 0; i --){
			int j = G[x][i];
			if(dss[j] == dss[x]){
				ds = j;
				break;
			}
		}
	}
	long long szs = 0;
	w[x] = a[x] * dep[x];
	for(int i = 0; i < G[x].size(); i ++){
		int j = G[x][i];
		if(T == 1 && j == ds && fl) continue;
		//printf("\t%d %d\n", x, j);
		dfs2(j, false);
		w[x] += 2 * sum[j] * szs + w[j];
		szs += siz[j];
	}
	if(T == 1 && siz[x] > 1 && fl){
		//printf("\t1:%d %d\n", x, ds);
		dfs2(ds, true);
		w[x] += 2 * sum[ds] * szs + w[ds];
	}
}

int main(){
	scanf("%d %d", &n, &T);
	for(int i = 2; i <= n; i ++){
		int f;
		scanf("%d %lld", &f, &a[i]);
		G[f].push_back(i);
	}
	dfs(1, 0);
	dfs2(1, true);
	if(T == 0){
		printf("%d %lld", (n - 1) * 2, w[1]);
	}else{
		printf("%d %lld", (n - 1) * 2 - maxd, w[1]);
	}
	return 0;
}

只有 T=1T=1 的情况没过,主要思想是把子节点排序,然后把从根节点出发的最长链拎出来最后单独计算,然后调了一个下午……

2023/10/4 21:02
加载中...