给你一棵树。树上的每一个点有一个权值
W
W
W。
你需要找到所有距离为
2
2
2 的点对
(
i
,
j
)
(i,j)
(i,j) ,它们的“星座权值”为
W
i
∗
W
j
Wi*Wj
Wi∗Wj。
求最大的“星座权值”和所有“星座权值”的和。
解
60pts:
逐个枚举点。走一步,再走一步,处理。
或者DFS。?各种数组乱套。
70pts:
加个快读。?
100pts:
逐个枚举点,它相连的点间处理权值。
再化简式子,优化,用sum。
代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
int n, x, y, t, tot, w[300005], ans1, ans2, l[300005], sum, maxx;
struct asdf{
int to, next;
} a[4000003];
int read(){
int lll = 0;
char c = getchar();
while(c > '9' || c < '0') c = getchar();
while(c <= '9' && c >= '0'){
lll = lll * 10 + c - 48;
c = getchar();
}
return lll;
}
int main(){
freopen("link.in","r",stdin);
freopen("link.out","w",stdout);
n = read();
for(int i = 1; i < n; ++i){
x = read();
y = read();
a[++t] = (asdf){y, l[x]}; l[x] = t;
a[++t] = (asdf){x, l[y]}; l[y] = t;
}
for(int i = 1; i <= n; ++i)
scanf("%d", &w[i]);
for(int i = 1; i <= n; ++i){ //枚举点
sum = 0; maxx = 0;
for(int j = l[i]; j; j = a[j].next){ //走一步
ans2 = (ans2 + sum * w[a[j].to] * 2) % 10007; //加上权值
ans1 = max(ans1, maxx * w[a[j].to]); //找最大权值
sum += w[a[j].to]; //统计能走的点的和,这样就不比再走个循环
sum = sum % 10007;
maxx = max(maxx, w[a[j].to]); //更新最大的点
}
}
printf("%d %d", ans1,ans2); //输出答案
fclose(stdin);
fclose(stdout);
}