無向連通圖G 有n 個點,n - 1 條邊。點從1 到n 依次編號,編號爲 i 的點的權值爲W i ,每條邊的長度均爲1 。圖上兩點( u , v ) 的距離定義爲u 點到v 點的最短距離。對於圖G 上的點對( u, v) ,若它們的距離爲2 ,則它們之間會產生Wu×Wv 的聯合權值。ios
請問圖G 上全部可產生聯合權值的有序點對中,聯合權值最大的是多少?全部聯合權值之和是多少?ide
輸入格式:spa
輸入文件名爲link .in。code
第一行包含1 個整數n 。blog
接下來n - 1 行,每行包含 2 個用空格隔開的正整數u 、v ,表示編號爲 u 和編號爲v 的點之間有邊相連。ip
最後1 行,包含 n 個正整數,每兩個正整數之間用一個空格隔開,其中第 i 個整數表示圖G 上編號爲i 的點的權值爲W i 。it
輸出格式:io
輸出文件名爲link .out 。event
輸出共1 行,包含2 個整數,之間用一個空格隔開,依次爲圖G 上聯合權值的最大值class
和全部聯合權值之和。因爲全部聯合權值之和可能很大,輸出它時要對10007 取餘。
輸入樣例#1:
5
1 2
2 3
3 4
4 5
1 5 2 3 10
輸出樣例#1:
20 74
本例輸入的圖如上所示,距離爲2 的有序點對有( 1,3) 、( 2,4) 、( 3,1) 、( 3,5) 、( 4,2) 、( 5,3) 。
其聯合權值分別爲2 、1五、2 、20、1五、20。其中最大的是20,總和爲74。
【數聽說明】
對於30% 的數據,1 < n≤ 100 ;
對於60% 的數據,1 < n≤ 2000;
對於100%的數據,1 < n≤ 200 , 000 ,0 < wi≤ 10, 000 。
noip2014提升組day1第二題
------------------------------------------------------------------------------------------------------------------------------------------------
講解:
對於這題,最煩的一點是兩點之間的距離爲2,這意味着不能直接搜,可是咱們能夠找一箇中轉站i,設與i相連的點編號分別爲
一、二、3……,點1的權爲w1,那麼所產生的聯合權值S=(w1*w2+w1*w3+w1*w4+w2*w3+w2*w4+w3*w4)*2(由於是有序點對)
因此S=(w1+w2+w3+w4)*(w1+w2+w3+w4)-w1*w1-w2*w2-w3*w3-w4*w4咱們只須要統計點一、二、三、4的權的和sum和權的平
方和的差就是i點所連的點產生的聯合權值,最後求S的和即爲聯合權值的總和。
對與最大值,咱們能夠在每條邊所鏈接的兩點互相更新最大和次大值,再把每一個點的兩個值相乘的最大值
代碼實現:
#include<iostream> #include<cmath> #include<algorithm> #include<cstdio> using namespace std; const int p=10007;//取餘 int n,a[200010],b[200010][2],sum[200010][2],maxn[200010][3],ans,maxx; void ff(int x,int y) { maxn[x][2]=a[y]; sort(maxn[x],maxn[x]+3); maxn[x][0]=maxn[x][2]; //maxn[x][1]=maxn[x][1]; maxx=max(maxx,maxn[x][0]*maxn[x][1]);//更新總的最大值 //----------------------------------------------------------------------- sum[x][0]=(sum[x][0]+a[y])%p; sum[x][1]=(sum[x][1]+a[y]*a[y])%p; //鏈接兩條邊時一塊兒統計(w1+w2+w3+...+wn)*(w1+w2+w3+...+wn)和(w1*w1+w2*w2+w3*w3+...wn*wn)的值 return; } int main() { int i,j; scanf("%d",&n); for(i=1;i<=n-1;i++) scanf("%d%d",&b[i][0],&b[i][1]); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=1;i<=n-1;i++) { ff(b[i][0],b[i][1]); ff(b[i][1],b[i][0]);//對這條邊的兩點互相統計最大和次大值 總和 } for(i=1;i<=n;i++) ans=(ans+sum[i][0]*sum[i][0]-sum[i][1])%p;//總和 cout<<maxx<<" "<<ans; return 0; }