傳送門
無向連通圖 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取餘。
本蒟蒻在做題的過程中換過n次方法,但都只得到30分(原因:o(n3)暴力),最終還是看了題解,發現網上的方法大多是o(n2)的時間複雜度,但仍有大神將其強行壓到了o(n)。
o(n)做法核心:以列舉邊代替列舉點。
①列舉每一條邊,並分別嘗試用其中一點的權值更新另一點所能到達的點的最大和次大權值。
②o(n)效率用每一點的最大和次大權值計算聯合權值並更新答案。
③列舉每一條邊,計算每個點到達的所有點的權值sum。
④列舉每一條邊,計算該邊連線的兩點聯合權值並累加。(方法:用點1的sum減去點2的權值再乘以點2的權值即為以點2出發,經過點1所得到的所有權值。由於點對(a,b)和(b,a)不同,所以不必擔心重複)
#include
#include
using namespace std;
const int m=10007;
int n,i,s,ans;
struct aa
a[200000];
int w[200001];
int s1[200001];
int s2[200001];
int sum[200001];
void read(int &s)
int main()
else
if(w[a[i].y]>s2[a[i].x]) s2[a[i].x]=w[a[i].y];
if(w[a[i].x]>s1[a[i].y])
else
if(w[a[i].x]>s2[a[i].y]) s2[a[i].y]=w[a[i].x];
}for(i=1;i<=n;i++)
s=max(s,s1[i]*s2[i]);
for(i=1;i<=n-1;i++)
for(i=1;i<=n-1;i++)
printf("%d
%d",s,ans);
}
NOIP2014 聯合權值
鄰接表儲存樹。列舉每個節點,使之作為中點,先計算出與其相連的所有節點的權值總和l,與其相連的所有節點在該節點處形成的權值 l w w。如果沒有l,直接列舉以此節點為中點的節點對則只能過60 的資料。include include include include include include inc...
NOIP 2014 聯合權值
評測傳送 70分 列舉中間點,然後再兩層迴圈列舉這個點的所有鄰接點,兩兩相乘,加入和中。可能退化為n 2 100分 在70分的基礎上加乙個優化,當我們列舉了中間點,然後再列舉它的鄰接點 j 時,用sum i 表示 i 的所有鄰接點的權值的和,那麼以 i 作為中間點,j這個點對答案的貢獻為 sum i...
(noip2014)聯合權值
題目傳送門sxazr 本題可直接列舉每個點,然後列舉與它相連的兩個點,這兩個點的乘積便是乙個聯合權值 可以記錄下每個點與它相連的點的最大值和次大值,結果就是取最大值和次大值乘積的最大 求和的話,可以記錄下乙個點相連所有點的和s i sum w j s i w j j是與i相連的點 列舉每個點的sum...