NOIP2014day1之聯合權值

2022-08-22 11:15:11 字數 3151 閱讀 5236

noip2014day1有個題目叫聯合權值

題目描述

無向連通圖 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 個用空格隔開的正整數 u、v,表示編號為 u 和編號為 v 的點 之間有邊相連。

最後 1 行,包含 n 個正整數,每兩個正整數之間用乙個空格隔開,其中第 i 個整數表示 圖 g 上編號為 i 的點的權值為wi

。輸出格式

輸出共 1 行,包含 2 個整數,之間用乙個空格隔開,依次為圖 g 上聯合權值的最大值 和所有聯合權值之和。由於所有聯合權值之和可能很大,輸出它時要對10007取餘。

樣例輸入

5 1 2 

2 3 

3 4 

4 5 

1 5 2 3 10 

樣例輸出

20 70

限制對於 30%的資料,1 < n ≤ 100;

對於 60%的資料,1 < n ≤ 2000;

對於 100%的資料,1 < n ≤ 200,000,0 <wi

這麼一道題,有乙個很顯而易見的做法,n^2列舉,當然,只能拿60分

題目上說n-1條邊的無向連通圖,實際上就是告訴我們這是一棵樹,那麼很顯然是不存在環的

而距離為2的點,實際上就是與每個點直接存在邊相連的任意兩個不同點

那麼很輕易可以想到要列舉中間點,然後對於它周圍一圈的點進行計算

因為是樹不存在環,所以可以確保計算不重複

最大值很輕易,就是周圍一圈點中最大兩個點的乘積取最大值

那麼剩下就是求和的問題了

如果不考慮時間和空間,就是雙重迴圈跑一趟就好了

然後可以發現,對於周圍這一圈每個點都要與其他點相乘

那麼對於每個點,設sum=周圍一圈點的權值和,wi

又因為是有序點對,(i,j)和(j,i)被認為不同

那麼每個點對答案都有乙個wi*(sum-wi)的貢獻,那麼只要跑一趟就可以了

複雜度是o(n)的,因為每條邊最多兩次被參與計算

**在下面

const tt=10007; 

var link,a:array[0..200005

]of longint;

son,next:array[

0..400005

]of longint;

n,tot,ans1,ans:longint;

procedure add(x,y:longint);

begin

inc(tot);son[tot]:=y;next[tot]:=link[x];link[x]:=tot;

end;

procedure init;

varx,y,i,j:longint;

begin

assign(input,

'link.in

');reset(input);

assign(output,

'link.out

');rewrite(output);

fillchar(link,

sizeof(link),0

); readln(n);

tot:=0

;

for i:=1 to n-1

dobegin

readln(x,y);

add(x,y);add(y,x);

end;

for i:=1 to n do

read(a[i]);

end;

procedure main;

vari,j,x,y,sum:longint;

begin

a[0]:=0

; ans:=0;ans1:=0

;

for i:=1 to n do

begin

sum:=0;x:=0

; j:=link[i];

while j<>0

dobegin

if a[son[j]]>a[x] then x:=son[j];

sum:=(sum+a[son[j]])mod tt;

j:=next[j];

end;

j:=link[i];y:=0

;

while j<>0

dobegin

if (a[son[j]]>a[y])and(son[j]<>x) then y:=son[j];

ans:=(ans+a[son[j]]*(sum+tt-a[son[j]]))mod tt;

j:=next[j];

end;

if a[x]*a[y]>ans1 then ans1:=a[x]*a[y];

end;

end;

procedure print;

begin

writeln(ans1,''

,ans);

close(input);close(output);

end;

begin

init;

main;

print;

end.

還發生了小插曲

我寫好後,測評只有20

和學長認認真真檢查了乙個晚上,發現取模錯了,應該對10007,我寫成了70007

最後,學長語重心長的說「聽我的,撞牆吧,網上幾千份,你剛好點開了錯了」

qaq尷尬

【寫的有漏洞的,歡迎路過大神吐槽】

2016-11-01 13:37:00

ending.

NOIP2014day1 聯合權值

首先這是棵樹,那麼任意兩點間就只有一條路徑。要想值為2,那麼就需要兩個點連到同乙個點,即與同乙個點直接相連 那麼我們就可以列舉中間的點,然後遍歷它所有與其相連的點。另外總和權值可以這麼算 假如有兩個點 2ab a b 2 a2 b2 2ab a b 2 a 2 b 2 2ab a b 2 a2 b2...

NOIP2014 Day1 T2 聯合權值

noip2014 day1 t2 聯合權值 time limit 10000ms memory limit 131072k total submit 57 accepted 30 case time limit 1000ms description input output sample input...

NOIP 2014 day 1 T2 聯合權值

第一眼看起來很複雜。所以我想了個對鏈 和樹不同情況都分別處理的演算法。orz。複雜度太高最後4組t了。所以。轉換思路。聯合權值 w i w j i,j距離為2.也就是i,j中間間隔了乙個節點,所以我們在遍歷這個中間節點的時候處理。題目求最大和總和,先考慮最大,我們只需要對節點u維護乙個 max1,m...