洛谷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 資料範圍及提...