noip2014联合权值
题目描述
无向连通图G有n个点,n-1条边。点从1到n依次编号,编号为i的点的权值为Wi ,每条边的长度均为1。图上两点(u, v)的距离定义为u点到v点的最短距离。对于图G上的点对(u, v),若它们的距离为2,则它们之间会产生Wu×Wv的联合权值。
请问图G上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少?
输入格式
第一行包含1个整数n。
接下来n-1行,每行包含2个用空格隔开的正整数u、v,表示编号为u和编号为v的点之间有边相连。
最后1行,包含n个正整数,每两个正整数之间用一个空格隔开,其中第i个整数表示图G上编号为i的点的权值为Wi。
输出格式
输出共1行,包含2个整数,之间用一个空格隔开,依次为图G上联合权值的最大值
和所有联合权值之和。由于所有联合权值之和可能很大,输出它时要对10007取余。
样例输入1
5
1 2
2 3
3 4
4 5
1 5 2 3 10
样例输出1
20 74
注释说明
样例解释
本例输入的图如上所示,距离为 2 的有序点对有(1,3) 、(2,4) 、(3,1) 、(3,5)、(4,2) 、(5,3)。
其联合权值分别为 2,15,2,20,15,20。其中最大的是 20,总和为 74。
数据规模
对于30%的数据,1<n≤100;
对于60%的数据,1<n≤2000;
对于100%的数据,1<n≤200,000,0<Wi ≤10,000。
题目来源
noip2014提高组day1第2题
#include <bits/stdc++.h>
using namespace std;
long long ans2;
int n,w[200001],k,ans,n1,n2,p=10007;
vector<int>e[200002];
void dfs(int x,int fa,int g){
int f1=0,f2=0;
long sq=0,sum=0;
for(int i=0;i<e[x].size();i++){
int yy=e[x][i],y=w[yy];
if(yy==fa)continue;
sq=(sq+y*y)%p;
sum+=y;
if(y>f1)f2=f1,f1=y;
else if(y>f2)f2=y;
dfs(yy,x,fa);
}
ans=max(ans,f1*f2);
ans=max(ans,w[g]*w[x]);
sum%=p;
ans2=(ans2+(sum*sum)%p-sq+2*(w[g]*w[x])%p)%p;
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
for(int i=1;i<=n;i++){
scanf("%d",&w[i]);
}
dfs(1,0,0);
printf("%d %d\n",ans,ans2);
}
标签:f2,noip2014,20,int,权值,联合,ans
From: https://blog.csdn.net/no_play_no_games/article/details/142440150