1. 程式人生 > >#樹#洛谷 1351 jzoj 3931 聯合權值

#樹#洛谷 1351 jzoj 3931 聯合權值

題目

在一棵樹中找出無序點對 ( a , b ) (a,b) ,使 a

a b b 的距離為2,問 w a ×
w b m o d    10007 \sum w_a\times w_b\mod10007
以及 m a x ( w [ a ] × w [ b ] ) max(w[a]\times w[b])


分析

一棵樹上兩點路徑只有一條,所以說符合要求的其中一個點對都必然與一個點相連,所以可以列舉中間點,求出答案


程式碼

#include <cstdio>
#define rr register
using namespace std;
struct node{int y,next;}e[400001];
int n,ls[200001],w[200001],k=1;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (c<48||c>57) c=getchar();
	while (c>47&&c<58) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
	return ans;
}
inline void add(int x,int y){
	e[++k]=(node){y,ls[x]}; ls[x]=k;
	e[++k]=(node){x,ls[y]}; ls[y]=k;
}
signed main(){
	n=iut(); long long ans=0,ans1=0;
	for (rr int i=1;i<n;++i) add(iut(),iut());
	for (rr int i=1;i<=n;++i) w[i]=iut();
	for (rr int i=1;i<=n;++i){
		rr int maxx=w[e[ls[i]].y],sum=w[e[ls[i]].y];
		for (rr int j=e[ls[i]].next;j;j=e[j].next){
			ans=(ans+1ll*sum*w[e[j].y])%10007; sum+=w[e[j].y];
			ans1=ans1>(1ll*maxx*w[e[j].y])?ans1:(1ll*maxx*w[e[j].y]);
			maxx=maxx>w[e[j].y]?maxx:w[e[j].y];
		}
	}
	printf("%lld %lld",ans1,ans*2%10007);
	return 0;
}