NOIP2014 联合权值 解题报告
来源:互联网 发布:chrome 黑客 js 编辑:程序博客网 时间:2024/05/22 06:54
描述
无向连通图 G 有 n 个点,n-1 条边。点从 1 到 n 依次编号,编号为 i 的点的权值为
, 每条边的长度均为 1。图上两点(u, v)的距离定义为 u 点到 v 点的最短距离。对于图 G 上的点对(u, v),若它们的距离为 2,则它们之间会产生
×
的联合权值。
请问图 G 上所有可产生联合权值的有序点对中,联合权值最大的是多少?所有联合权值之和是多少?
格式
输入格式
第一行包含 1 个整数 n。
接下来 n-1 行,每行包含 2 个用空格隔开的正整数 u、v,表示编号为 u 和编号为 v 的点 之间有边相连。
最后 1 行,包含 n 个正整数,每两个正整数之间用一个空格隔开,其中第 i 个整数表示 图 G 上编号为 i 的点的权值为
。
输出格式
输出共 1 行,包含 2 个整数,之间用一个空格隔开,依次为图 G 上联合权值的最大值 和所有联合权值之和。由于所有联合权值之和可能很大,输出它时要对10007取余。
样例1
样例输入1[复制]
51 22 33 44 51 5 2 3 10
样例输出1[复制]
20 74
限制
对于 30%的数据,1 < n ≤ 100;
对于 60%的数据,1 < n ≤ 2000;
对于 100%的数据,1 < n ≤ 200,000,0 <
≤ 10,000。
提示
本例输入的图如上所示,距离为 2 的有序点对有(1,3)、(2,4)、(3,1)、(3,5)、(4,2)、(5,3)。 其联合权值分别为 2、15、2、20、15、20。其中最大的是 20,总和为 74。
样例数据:
5
1 2
2 3
3 4
4 5
1 5 2 3 10
样例输出
20 74
具体操作:
S[i](边)
1
2
3
4
5
W[i]
1
5
2
3
10
Max1[i]
2
2
5
10
3
Max2[i]
/
1
3
2
/
即由表可知,除去1,5点后共有6组即距离为2的有序点对有(1,3)、(2,4)、(3,1)、(3,5)、(4,2)、(5,3)。其联合权值分别为2、15、2、20、15、20。其中最大的是20,总和为74。
分析:
总的来说,本体让求两个值,一个所有权值联合后的和,二是最大的联合权值,那好,我们暂且先来看看这最大的联合权值
所谓联合权值,就是两个距离为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*f+e*g....,但其实我们这样处理,我们先用加法运算法则,发现sum其实就是每个点的权值乘以可以联合(距离为2)的节点的所有权值之和,所以说,我们在读入数据的时候,可以预先处理一下,把每个节点周围相邻节点的权值之和给加起来,就以上述为例,在处理时,把a,b,c....g的权值加起来为s[o](O点相邻点的权值之和),然后在计算时,就可以用sum:=a*(s[o]-a)+b*(s[o]-b).....很自然的结果就出来了!
对上述算法进行效率分析,可知,似乎没有一个地方要用到两层循环,时间复杂度无限接近于O(n),肯定不超时的!!!
参考程序
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;vara,b:longint);//注意,这个过程是比大小的,但由于比较的结果必须返回,所以必须用全局变量,括号里的var是不可或缺的
begin
ifx>a then
begin
b:=a; a:=x;
end
else
ifx>b then b:=x;
end;
begin
readln(n);
fori:=1 to n-1 do readln(e[i].u,e[i].v);//读入每个边的两个端点
fori:=1 to n do read(w[i]);//读入权值
fori:=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;
fori:=1 to n do if max1[i]*max2[i]>ans1 then ans1:=max1[i]*max2[i];//计算最大的联合权值
fori:=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.
(2)、代码详解:
program quan1;
type
rec=record
u,v:longint;
end; ////////////////一条边的左右两个顶点
var
n,i,j,ans1,ans2,u,v:longint;
s:array[1..200000]of longint; ////////////////用来存放一个顶点上与它相连的其他顶点权值之和
w,max1,max2:array[1..200000]of longint;/////////w存放权值,max1,2是分别用来存储连接一个
e:array[1..200000]of rec; //顶点的最大值次大值的数组
procedure compare_1(x:longint; vara,b:longint);//////即上述寻找最大值次大值的过程
begin
ifx>a then begin
b:=a; a:=x;//若x为最大值,则将最大值赋给a,由b保存次大值,即此处的a
end
else
ifx>b then b:=x;//////当b<x<a时,将x赋值给b{a(max1):最大值 b(max2):次大值}
end;
//////////////////////////main////////////////////////////
begin
readln(n);//读入n(点数);
fori:=1 to n-1 do
readln(e[i].u,e[i].v);//读入边I的两个顶点
fori:=1 to n do read(w[i]);//读入权值
fori:=1 to n-1 do
begin
u:=e[i].u; v:=e[i].v; //边i的两个顶点
inc(s[u],w[v]); /////不断将结点相邻的权值加入该结点的s
inc(s[v],w[u]); //同上
compare_1(w[v],max1[u],max2[u]); //////即上述的寻找最大值,次大值并加入数组
compare_1(w[u],max1[v],max2[v]); //////即上述的寻找最大值,次大值并加入数组
end;
fori:=1 to n do if max1[i]*max2[i]>ans1then ans1:=max1[i]*max2[i];/// 即所求最大联合权
fori:=1 to n-1 do //n-1条边 /值
begin
u:=e[i].u; v:=e[i].v;
ans2:=(ans2+(s[u]-w[v])*w[v] mod 10007)mod 10007; ///对于一条边i分别将
ans2:=(ans2+(s[v]-w[u])*w[u] mod 10007)mod 10007; //其两个顶点的联合权值之积
end; // 加入ans2(和);
writeln(ans1,' ',ans2);//分别输出
end.
- NOIP2014 联合权值 解题报告
- LuoguP1351[NOIP2014] 联合权值 解题报告【树形DP】
- NOIP2014 联合权值 解题报告(乱搞(据说这道题是树状dp,感觉好像是))
- NOIP2014 联合权值
- NOIP2014联合权值
- NOIP2014联合权值
- 【noip2014】联合权值
- NOIP2014 联合权值
- 【NOIP2014】 联合权值
- noip2014联合权值
- NOIP2014 联合权值
- 【NOIP2014】联合权值
- 【NOIP2014 联合权值】
- [NOIP2014]联合权值
- NOIP2014联合权值
- [noip2014]联合权值
- 【解题报告】CodeVS3728 联合权值
- 【NOIP2014提高】联合权值
- Hibernate @Temporal的使用
- DM3730芯片的相关使用经验 和 DM3730的中文文档:
- Nginx的http反向代理初探
- tomcat8.0一个坑爹的问题:Unable to compile class for JSP:
- css 完全居中
- NOIP2014 联合权值 解题报告
- 【二十】关于利用squidclient分析日志未命中情况寻求优化
- button设置
- Redis使用误区
- 27-网络编程-19-网络编程(TCP协议-练习-服务端多线程技术)
- Tsung负载测试工具
- cocosdx里面A*算法的实现#ifndef __CAT_SPRITE_H__ #define __CAT_SPRITE_H__ #include "HelloWorldScene.h" #incl
- git push origin master
- Python 之 sklearn 实现 PCA 降维