联合权值

题目链接

两年前调了一个周的题在做还是不会,,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;
}
posted @ 2020-09-11 08:58  zlq,  阅读(119)  评论(0编辑  收藏  举报