【題解】LuoGu1351:聯合權值

原題傳送門
因爲只有距離爲2的點對才能產生貢獻,所以這道題目很簡單
對於每個點所有與它相連的點兩兩之間是距離爲2的,令這些點的權值分別爲a1,a2,...,ama_1,a_2,...,a_m
這些點的權值乘積和就是a1(a2+a3+...+am)+a2(a1+a3+...+am)+...+am(a1+a2+...+am1)a_1*(a_2+a_3+...+a_m)+a_2*(a_1+a_3+...+a_m)+...+a_m*(a_1+a_2+...+a_{m-1})
=a1(sa1)+a2(sa2)+...+am(sam)(s=i=1mai)=a_1*(s-a_1)+a_2*(s-a_2)+...+a_m*(s-a_m)(令s=\sum_{i=1}^{m}a_i)
遍歷整棵樹就可以得到答案
最大權值乘積就是記一個最大值和次大值就好了
Code:

#include <bits/stdc++.h>
#define maxn 200010
#define qy 10007
#define int long long
using namespace std;
struct Edge{
	int to, next;
}edge[maxn << 1];
int num, head[maxn], val[maxn], n, ans, MAX;

inline int read(){
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

void addedge(int x, int y){ edge[++num] = (Edge){y, head[x]}, head[x] = num; }

void dfs(int u, int pre){
	int s = 0, Max = 0, sec = 0;
	for (int i = head[u]; i; i = edge[i].next){
		int v = edge[i].to;
		s += val[v];
		if (val[v] > Max) Max = val[v]; else
		if (val[v] > sec) sec = val[v];
		if (v != pre) dfs(v, u);
	}
	MAX = max(MAX, Max * sec);
	for (int i = head[u]; i; i = edge[i].next){
		int v = edge[i].to;
		(ans += val[v] * (s - val[v]) % qy) %= qy;
	}
}

signed main(){
	n = read();
	for (int i = 1; i < n; ++i){
		int x = read(), y = read();
		addedge(x, y), addedge(y, x);
	}
	for (int i = 1; i <= n; ++i) val[i] = read();
	dfs(1, 0);
	printf("%lld %lld\n", MAX, ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章