联合权值
两年前调了一个周的题在做还是不会,,QAQ写篇博客纪念一下
显然(?),连通图 + n个点n-1条边 = 树
显然(?),和点i距离为2的点是他的爷爷或者兄弟,中间都隔着他的父亲
因为是无向图,直接正反建边,把父亲当做儿子处理(父慈子孝
然而枚举两两组合是需要n方的,t飞
(敲黑板!)
a*b=[(a+b)2-a2-b^2]/2
a,b,c,……,n也是同理,两两的乘积都等于和的平方-平方和再除以2
n方就变成n了
另外有序点对(1,2)和(2,1)都会算,也就不需要除以2了
另外注意题目中联合权值和需要取模,最大联合权值并不需要!!!
#include<bits/stdc++.h>
using namespace std;
int head[1000000],mod=10007,w[1000000],answer=0,cnt=0;
struct node{
int to,nxt;
}road[500000];
void build(int u,int v)
{
road[++cnt].to=v;
road[cnt].nxt=head[u];
head[u]=cnt;
}
int main()
{
int n,maxn=0;
cin>>n;
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
build(u,v);
build(v,u);
}
for(int i=1;i<=n;i++) cin>>w[i];
for(int i=1;i<=n;i++)
{
int sum=0,ans=0,max1=0,max2=0;
for(int j=head[i];j;j=road[j].nxt)
{
int v=road[j].to;
sum=(sum+w[v]+mod)%mod;
ans=(ans+w[v]*w[v]+mod)%mod;
if(w[v]>max1) max2=max1,max1=w[v];
else if(w[v]>max2) max2=w[v];
}
ans=((sum*sum+mod)%mod-ans+mod)%mod;//有序点对一对点算两次不用除以2
answer=(answer+ans+mod)%mod;//别忘了取模啊
maxn=max(maxn,max1*max2);
}
cout<<maxn<<" "<<answer;
return 0;
}