题目描述
无向连通图G 有n 个点,n - 1 条边。点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 。图上两点( u , v ) 的距离定义为u 点到v 点的最短距离。对于图G 上的点对( u, v) ,若它们的距离为2 ,则它们之间会产生Wu×Wv 的联合权值。
请问图G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少?
思路:注意题目中这是一个无向连通图,且被n-1条边连着,这让我们想起什么呢,这就是一个树,而且退化成了一条链。所以我们只要枚举每个点,然后跟他连着的点的权值相乘就好了,最后还要乘以二,因为题目中要求我们求a—b&&b—a(就这么简单,懒得敲代码,上网找了一篇,放心,我会给你们注释的很明白的)
1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 struct Edge 5 { 6 int t,nexty; 7 }edge[1000000];//链式前向星,不明白的没关系我可能已经发表了关于链式前向星的博客,请前去看看 8 int head[300000]={0},cnt=0;//关于建图 9 void add(int a,int b) 10 { 11 cnt++; 12 edge[cnt].t=b,edge[cnt].nexty=head[a]; 13 head[a]=cnt; 14 } 15 long long w[300000]={0};//w数组代表点的值 16 int main() 17 { 18 int n;//n个点 19 scanf("%d",&n);//输入 20 int a,b;//a点,b点 21 for(int i=0;i<n-1;i++) 22 { 23 scanf("%d%d",&a,&b);//输入a,b俩点 24 add(a,b),add(b,a);//a,b俩点之间建边 25 } 26 for(int i=1;i<=n;i++)scanf("%lld",&w[i]);//输入点的值 27 long long sum=0,maxn=0;//sum记录着联合权值的总和,maxn记录最大值的联合权值 28 long long he,rmax;//he表示当前的和,rmax是指当前的最大值 29 int node;//后面领悟吧,不好说,可以换掉这个 30 for(int i=1;i<=n;i++) 31 { 32 node=head[i];//这关 33 he=(rmax=w[edge[node].t])%10007;//此时的he要等于他的一条边连这那个点的值 34 node=edge[node].nexty;//换另一条边 35 for(;node!=0;node=edge[node].nexty)//核心代码,后方高能 36 { 37 sum=(sum+he*w[edge[node].t])%10007;//总和要加上联合权值的和 38 maxn=max(maxn,rmax*w[edge[node].t]);//最大值要与此时的最大值进行比较 39 he=(he+w[edge[node].t])%10007;//和要加上第二条边所连点的值 40 rmax=max(rmax,w[edge[node].t]);//rmax进行更新 41 } 42 } 43 printf("%lld %lld",maxn,(sum*2)%10007);//输出 44 return 0; 45 }
原文地址:https://www.cnblogs.com/tpgzy/p/8903355.html
时间: 2024-10-03 10:30:47