zoukankan      html  css  js  c++  java
  • NOIP 2014 D1T2 -联合权值

    联合权值

    (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.
  • 相关阅读:
    mysql系列--基础知识
    微信开发(2)–获取access_token
    微信开发(1)–开发模式
    https协议 ssl协议以及证书生成
    ▲▲▲▲▲ Daodantou 小练习▲▲▲▲▲
    第十三章 模块[DDT书本学习 小甲鱼]【1】
    第十一章 类和对象[DDT书本学习 小甲鱼]【3】
    第十一章 类和对象[DDT书本学习 小甲鱼]【2】
    第十一章 类和对象[DDT书本学习 小甲鱼]【1】
    hexdump(b,step,sep,decimal) 和 server、client 端 [北极星]
  • 原文地址:https://www.cnblogs.com/kry-ssw-1314/p/4562217.html
Copyright © 2011-2022 走看看