聯合權值(link)

2021-08-21 11:27:07 字數 1391 閱讀 6302

洛谷p1351

noip2014 day1 t2

無向連通圖 g 有 n 個點,n-1 條邊。點從 1 到 n 依次編號,編號為 i 的點的權值為 w[i] ,每條邊的長度均為 1。圖上兩點(u, v)的距離定義為 u 點到 v 點的最短距離。對於圖 g 上的點對(u, v),若它們的距離為 2,則它們之間會產生w[u]*w[v]的聯合權值。請問圖 g 上所有可產生聯合權值的有序點對中,聯合權值最大的是多少?所有聯合權值之和是多少?

由於此題只需要把距離為2的邊統計出來,因此可以把每一類距離為2的邊分類討論。顯然,這道題是一棵樹。可以看出,這種邊只有兩種,一種是祖先-父親-兒子(以下稱祖孫邊),另一種是同乙個父親的兄弟邊。對於祖孫邊,很好處理,對於要處理的點,把每個孫子點列出來,祖孫邊的權值就知道了。對於兄弟邊,只要把當前處理的點的每乙個兒子都遍歷一遍,經過父親和其它兒子點就自然而然是一條兄弟邊。如果要每乙個兒子點和其它每乙個兒子點都做一遍,時間複雜度太高了,所以可以用字首和。至於最大權值,可以把最大的兩個點記錄下來,它們的聯合權值肯定是這些兄弟邊中最大的。

看程式吧:

#include

#include

#include

using

namespace

std;

int n,w[200005],ans,s,b[200005];//s表示聯合權值和,ans表示最大聯合權值

vector

a[200005];

void dfs(int x)

else

if (w[a[x][i]]>t2) t2=w[a[x][i]];

s=(s+w[a[x][i]]*t%10007)%10007;//處理兄弟邊

t+=w[a[x][i]];//維護字首和

t%=10007;//如果不做這一步會超過int_max,然後就錯了

for (int j=0;j//處理祖孫邊

}ans=max(ans,t1*t2);

for (int i=0;iif (b[a[x][i]]==0) dfs(a[x][i]);

}int main()

for (int i=1;i<=n;i++) scanf("%d",&w[i]);

dfs(1);//假設1號點為樹根

cout

<' '

<2%10007;//前面都是單向做的,所以答案要乘以2

}

這道題雖然不是很難,但我初測只有40分。我以為每一步都mod 10007,最後就不用了,測了樣例之後才想到要乘以2,可忘記還要mod 10007。改了之後還是只有70分,原來是字首和在計算的時候沒有mod 10007,這樣就超過了int_max,字首和就變成了負數。這次題目沒做好,原因還是細節沒有處理好。以後遇到mod的題目可一定要小心,每一步都要注意mod。

3728 聯合權值

無向連通圖g 有n 個點,n 1 條邊。點從1 到n 依次編號,編號為 i 的點的權值為w i 每條邊的長度均為1 圖上兩點 u v 的距離定義為u 點到v 點的最短距離。對於圖g 上的點對 u,v 若它們的距離為2 則它們之間會產生wu wv 的聯合權值。請問圖g 上所有可產生聯合權值的有序點對中...

聯合權值題解

無向連通圖 gg 有 n n 個點,n 1 role presentation style position relative n 1 n 1條邊。點從 1 1 到 n role presentation style position relative n n依次編號,編號為 i i 的點的權值為 ...

3728 聯合權值

時間限制 1 s 空間限制 128000 kb 題目等級 gold 題解檢視執行結果 題目描述 description 輸入描述 input description 輸出描述 output description 樣例輸入 sample input 樣例輸出 sample output 資料範圍及提...