码迷,mamicode.com
首页 > 其他好文 > 详细

NOIP 2014 D1T2 -联合权值

时间:2015-06-09 00:41:25      阅读:282      评论:0      收藏:0      [点我收藏+]

标签:

联合权值

(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个用空格隔开的正整数u、v,表示编号为u和编号为v的点之间有边相连。

最后1行,包含n个正整数,每两个正整数之间用一个空格隔开,其中第i个整数表示图G上编号为i的点的权值为Wi。

 

【输出】

输出文件名为link.out。

输出共1行,包含2个整数,之间用一个空格隔开,依次为图G上联合权值的最大值和所有联合权值之和。由于所有联合权值之和可能很大,输出它时要对10007取余。 

 

【输入输出样例】

link.in

link.out

5

1 2

2 3

3 4

4 5

1 5 2 3 10

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<≤100;

对于60%的数据,1<≤2000;

对于100%的数据,1<≤200,000,0<Wi ≤10,000。

 

对于每个距离为2的店,都会有且只有一个唯一的中间点,所以我们只要枚举这个中间点,将与它相邻的点的权值两两相乘就可以了;然而因为两两相乘的时间复杂度是O(n^2)的,所以我们可以把两两相乘当做和平方减去平方和,总时间复杂度O(nlogn)。

然而CCF的数据好像有点奇怪超范围了...没事能AC就行...

代码:

 1 const
 2   modd=10007;
 3 
 4 var
 5   ot,ne,g,f:array[0..200001]of longint;
 6   max,ans,n,e,a,b,i:longint;
 7 
 8 procedure addedge(x,y:longint);
 9 begin
10   ot[e]:=y; ne[e]:=g[x]; g[x]:=e; inc(e);
11   ot[e]:=x; ne[e]:=g[y]; g[y]:=e; inc(e);
12 end;
13 
14 procedure work(x:longint);
15 var
16   a:array[0..200001]of longint;
17   a1,a2,i,p:longint;
18 begin
19   p:=g[x]; a[0]:=0;
20   a1:=0; a2:=0;
21   while p<>-1 do
22     begin inc(a[0]); a[a[0]]:=f[ot[p]]; p:=ne[p]; end;
23   if a[0]<2 then exit;
24 
25   for i:=1 to a[0] do inc(a1,a[i]);
26   a1:=sqr((a1 mod modd))mod modd;
27   for i:=1 to a[0] do
28     begin
29       dec(a1,sqr(a[i]));
30       while a1<0 do inc(a1,modd);
31     end;
32   ans:=(ans+a1) mod modd;
33 
34   a1:=0;
35   for i:=1 to a[0] do
36     if a[i]>a2 then
37       if a[i]<a1 then a2:=a[i]
38                  else begin a2:=a1; a1:=a[i]; end;
39   if a1*a2>max then max:=a1*a2;
40 end;
41 
42 procedure ready;
43 begin
44   readln(n);
45   fillchar(g,sizeof(g),255); e:=0;
46   for i:=1 to n-1 do
47     begin
48       readln(a,b);
49       addedge(a,b);
50     end;
51   for i:=1 to n do read(f[i]);
52 end;
53 
54 procedure main;
55 begin
56   max:=0; ans:=0;
57   for i:=1 to n do work(i);
58   writeln(max, ,ans);
59 end;
60 
61 begin
62   ready;
63   main;
64 end.

 

NOIP 2014 D1T2 -联合权值

标签:

原文地址:http://www.cnblogs.com/kry-ssw-1314/p/4562217.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!