[NOIP2014]联合权值 题解

题目大意:

  有一棵树,求距离为2的点权的乘积的和以及最大值。

思路:

  枚举每一个点,则与其相邻的点互为距离为2的点。该部分的最大值为点权最大的两个点的积,和为点的权值和的平方减去每个点的平方,这样每条边都被跑了两次,所以复杂度为O(n)。

  用邻接表存储要开双倍数组(无向),当然像cyk大神一样直接跑边就不用考虑这个了。

代码:

  邻接表:

 1 #include<cstdio>
 2 const int mo=10007,M=200008;
 3 int cnt,x,y,n,i,ans,tot,w[M],v[M<<1],last[M<<1],head[M<<1];
 4
 5 void add(int x,int y) { v[++cnt]=y,last[cnt]=head[x],head[x]=cnt; }
 6
 7 int main()
 8 {
 9     scanf("%d",&n);
10     for (i=1;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
11     for (i=1;i<=n;i++) scanf("%d",&w[i]);
12     for (i=1;i<=n;i++)
13     {
14         int sum=0,max1=0,max2=0,j,o;
15         for (j=head[i];j;j=last[j])
16         {
17             o=w[v[j]];
18             sum=(sum+o)%mo;
19             if (o>max1) max2=max1,max1=o;
20             else if (o>max2) max2=o;
21             tot=(tot-o*o)%mo;
22         }
23         tot=(tot+sum*sum)%mo;
24         sum=max1*max2;
25         if (sum>ans) ans=sum;
26     }
27     printf("%d %d\n",ans,tot);
28     return 0;
29 }

  %%%cyk大神:

 1 #include<iostream>
 2 using namespace std;
 3 int i,n,maxx,ans,x[200005],y[200005],w[200005];
 4 int am[200005],am2[200005],s[200005],qs[200005];
 5 int main()
 6 {
 7     cin>>n;
 8     for (i=1;i<=n-1;i++) cin>>x[i]>>y[i];
 9     for (i=1;i<=n;i++) cin>>w[i];
10     for (i=1;i<=n-1;i++)
11       {
12           s[x[i]]=(s[x[i]]+w[y[i]])%10007;
13           qs[x[i]]=(qs[x[i]]+w[y[i]]*w[y[i]])%10007;
14           s[y[i]]=(s[y[i]]+w[x[i]])%10007;
15           qs[y[i]]=(qs[y[i]]+w[x[i]]*w[x[i]])%10007;
16           if (w[y[i]]>am[x[i]]) {am2[x[i]]=am[x[i]];am[x[i]]=w[y[i]];}
17           else if (w[y[i]]>am2[x[i]]) am2[x[i]]=w[y[i]];
18           if (w[x[i]]>am[y[i]]) {am2[y[i]]=am[y[i]];am[y[i]]=w[x[i]];}
19           else if (w[x[i]]>am2[y[i]]) am2[y[i]]=w[x[i]];
20       }
21     maxx=0;
22     for (i=1;i<=n;i++) maxx=max(maxx,am[i]*am2[i]);
23     ans=0;
24     for (i=1;i<=n;i++) ans=(ans+s[i]*s[i]-qs[i])%10007;
25     cout<<maxx<<‘ ‘<<ans;
26 }
时间: 2024-07-29 00:47:20

[NOIP2014]联合权值 题解的相关文章

[NOIP2014]联合权值

描述 无向连通图G有n个点,n-1条边.点从1到n依次编号,编号为i的点的权值为Wi  ,每条边的长度均为1.图上两点(u, v)的距离定义为u点到v点的最短距离.对于图G上的点对(u, v),若它们的距离为2,则它们之间会产生Wu×Wv的联合权值. 请问图G上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少? 输入格式 输入文件名为link.in. 第一行包含1个整数n. 接下来n-1行,每行包含2个用空格隔开的正整数u.v,表示编号为u和编号为v的点之间有边相连.

NOIP2014联合权值——史上最强解析

[解题思路] (虽然说下面的话可能有点多,但鄙人还是希望各位能看完,对理解大有裨益) 总的来说,本体让求两个值,一个所有权值联合后的和,二是最大的联合权值,那好,我们暂且先来看看这最大的联合权值 所谓联合权值,就是两个距离为2的节点的全职的乘积,那怎么乘着最大呢?对一个点来说,最大的乘积自然就是和它相邻的两个权值最大的节点的权值的乘积, 至于求这两个最大值,我们完全可以在读入数据的时候顺便处理一下嘛,举手之劳而已!! 对于所有的联合权值之和,我们要求你还是要有一点数学基础的,但也不高,三年级就足

Luogu P1351 联合权值 题解

这是一个不错的树形结构的题,由于本蒟蒻不会推什么神奇的公式其实是懒得推...,所以很愉快的发现其实只需要两个点之间的关系为祖父和儿子.或者是兄弟即可. 然后问题就变得很简单了,只需要做一个正常的DFS,遍历整棵树,同时判断有没有祖父,如果有就计算,然后遍历自己的儿子,每次判断最大的一个,然后用一个\(sum\)来维护这个点之前的所有兄弟的权值和,挨个计算即可. 具体操作见代码,如果有不懂的,代码里面具体解释. #include<bits/stdc++.h> #define clean(a,i)

noip2014联合权值

http://codevs.cn/problem/3728/ 我们要做的是计算距离为2的有序对权值之和及最大值,最大值好弄,但一一枚举是不可行的,因为n<=200000,我们可以预处理一下,每次读入边的时候我们把与当前顶点有边相连的所有点的权值中的最大值及次大值保存起来,然后用个O(n)时间就可以计算出来.至于权值和,我们可以这样,用s[i]存储与节点i相连的节点的权值和,枚举每条边(u,v),sigma((s[u]-w[v])*w[v]+(s[v]-w[u])*w[u])mod 1007 即是

【NOIP之旅】NOIP2014 day1 T2 联合权值

2.联合权值 (link.cpp/c/pas) [问题描述] 无向连通图G有n个点,n-1条边.点从1到n依次编号,编号为i的点的权值为Wi  ,每条边的长度均为1.图上两点(u, v)的距离定义为u点到v点的最短距离.对于图G上的点对(u, v),若它们的距离为2,则它们之间会产生Wu×Wv的联合权值. 请问图G上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少? [输入] 输入文件名为link.in. 第一行包含1个整数n. 接下来n-1行,每行包含2个用空格隔开

[NOIP2014] 提高组 洛谷P1351 联合权值

题目描述 无向连通图G 有n 个点,n - 1 条边.点从1 到n 依次编号,编号为 i 的点的权值为W i ,每条边的长度均为1 .图上两点( u , v ) 的距离定义为u 点到v 点的最短距离.对于图G 上的点对( u, v) ,若它们的距离为2 ,则它们之间会产生Wu ×Wv 的联合权值. 请问图G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少? 输入输出格式 输入格式: 输入文件名为link .in. 第一行包含1 个整数n . 接下来n - 1 行,

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 个用空格隔开的正整数 

Noip2014模拟赛解题心得【联合权值】

首先说明一下,我是一个刚刚进入oi界不到半年的蒟蒻--半年来,我是仅仅凭着兴趣和决心,在校队的一群dalao中瑟瑟发抖.我做的很多题目都是"苟"出来的,就比如说这次模拟赛中的"联合权值",仅凭暴力只坑了40分. 现在就从这道题目开始分析吧.题目如下: 标题: 联合权值 详情: 输入格式: 第一行包含 1 个整数 n. 接下来 n-1 行,每行包含 2 个用空格隔开的正整数 u.v,表示编号为 u 和编号为 v 的点 之间有边相连. 最后 1 行,包含 n 个正整数,

【学术篇】luogu1351 [NOIP2014提高组] 联合权值

一道提高组的题..... 传送门:题目在这里.... 现在都懒得更自己的blog了,怕是太颓废了_ (:з」∠) _ 好久没做题了,手都生了.(好吧其实是做题方面手太生了) 这题我都不想讲了,把代码一贴就算了呗.. 但还是要说说的.... 首先,题目里说:"无向连通图G 有n 个点,n - 1 条边." 我们可以知道这是一棵树(怕不是废话..),这样遍历的时候就能保证是O(n)级别了.. 找最大值 很简单,遍历树的时候找一下与每个点相连的点的最大值和次大值一乘就完了...显然这么贪心是