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

[解题思路]

(虽然说下面的话可能有点多,但鄙人还是希望各位能看完,对理解大有裨益)

总的来说,本体让求两个值,一个所有权值联合后的和,二是最大的联合权值,那好,我们暂且先来看看这最大的联合权值

所谓联合权值,就是两个距离为2的节点的全职的乘积,那怎么乘着最大呢?对一个点来说,最大的乘积自然就是和它相邻的两个权值最大的节点的权值的乘积,

至于求这两个最大值,我们完全可以在读入数据的时候顺便处理一下嘛,举手之劳而已!!

对于所有的联合权值之和,我们要求你还是要有一点数学基础的,但也不高,三年级就足够了!!你先想一想,我们怎么来求这个和呢?哦!无非就是把所有的

加起来而已嘛!对啊, 但是怎么加着快呢?你想一想,哦,一个点旁边有好多个点,每两个都乘一下,真的好麻烦啊!!有什么传说级别的算法能处理一下吗?

不,没有。有的只有一个,那叫做,加法结合律!!!

好吧,我也不装了,你想一想,和o点相邻的点有a,b,c,d,e,f,g七个,假设他们的权值就是a,b,c,d,e,f,g,二逼青年的计算过程是这样的:sum:=a·b+a·c+a·d…….+a….+e*g….,但其实我们这样处理,我们先用加法运算法则,发现sum其实就是每个点的权值乘以可以联合(距离为2)的节点的所有权值之和,所以说,我们在读入数据的时候,可以预先处理一下,把每个节点周围相邻节点的权值之和给加起来,就以上述为例,在处理时,把a,b,c….g的权值加起来为s[o]{o点相邻点的权值之和},然后在计算时,就可以用sum:=a·(s[o]-a)+b·(s[o]-b)…..很自然的结果就出来了!

对上述算法进行效率分析,可知,似乎没有一个地方要用到两层循环,时间复杂度无限接近于O(n),肯定不超时的!!!

[参考程序]

program link;
type
  edge=record//用来存储边,u和v代表两个节点
    u,v:longint;
  end;
var
 n,i,j,ans1,ans2,u,v:longint;
 s:array[1..200000]of int64;//s数组用来存储和节点i相邻的所有点的权值之和
 w,max1,max2:array[1..200000]of longint;//w数组用来存储每个边的权值,max1用来存储每个节点相邻节点中权值最大的节点权值,max2来存储次大的节点权值
 e:array[1..200000]of edge;//存储边
procedure work(x:longint;var a,b:longint);//注意,这个过程是比大小的,但由于比较的结果必须返回,所以必须用全局变量,括号里的var是不可或缺的
begin
  if x>a then
  begin
    b:=a; a:=x;
  end
    else
  if x>b then b:=x;
end;
begin
  readln(n);
  for i:=1 to n-1 do readln(e[i].u,e[i].v);//读入每个边的两个端点
  for i:=1 to n do read(w[i]);//读入权值
  for i:=1 to n-1 do //对值进行预处理
  begin
    u:=e[i].u; v:=e[i].v;
    inc(s[u],w[v]);//等同于s[u]:=s[u]+w[v],意在计算u节点的相邻节点的权值总和
    inc(s[v],w[u]);//同上
    work(w[v],max1[u],max2[u]);//不断地更新节点周围权值的最大与次大值
    work(w[u],max1[v],max2[v]);//同上
  end;
  for i:=1 to n do if max1[i]*max2[i]>ans1 then ans1:=max1[i]*max2[i];//计算最大的联合权值
  for i:=1 to n-1 do//对每条边的两个节点进行处理
  begin
    u:=e[i].u; v:=e[i].v;
    ans2:=(ans2+(s[u]-w[v])*w[v] mod 10007)mod 10007;
    ans2:=(ans2+(s[v]-w[u])*w[u] mod 10007)mod 10007;
  end;
  writeln(ans1,‘ ‘,ans2);
end.

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-06 10:54:02

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的点权的乘积的和以及最大值. 思路: 枚举每一个点,则与其相邻的点互为距离为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

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)级别了.. 找最大值 很简单,遍历树的时候找一下与每个点相连的点的最大值和次大值一乘就完了...显然这么贪心是

$Noip2014/Luogu1351$ 联合权值 树形

$Luogu$ $Description$ 给定一棵树,每两个距离为$2$的点之间可以产生"联合权值","联合权值"定义为这两个数的乘积.求最大的联合权值以及所有的联合权值之和.注意这两个数是有序的,翻译成人话就是求完和之后要$*2$. $Sol$ 想起了消防局的设立$ovo$. 距离为$2$的点,它们不是兄弟就是祖孙,那直接$dfs$一遍更新答案就好了叭. 兄弟之间更新答案这里有两个优化: 1.贪心.把所有的兄弟加入数组$s$之后按照$w[i]$从大到小排序,一遍