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.
  • 相关阅读:
    remove white space from read
    optimize the access speed of django website
    dowload image from requests
    run jupyter from command
    crawl wechat page
    python version 2.7 required which was not found in the registry windows 7
    health
    alternate rows shading using conditional formatting
    word
    【JAVA基础】static 关键字
  • 原文地址:https://www.cnblogs.com/kry-ssw-1314/p/4562217.html
Copyright © 2011-2022 走看看