1. 程式人生 > >luoguP1351 聯合權值

luoguP1351 聯合權值

mes truct 距離 數組 建圖 輸入a AC pac 之間

題目描述

無向連通圖G 有n 個點,n - 1 條邊。點從1 到n 依次編號,編號為 i 的點的權值為W i ,每條邊的長度均為1 。圖上兩點( u , v ) 的距離定義為u 點到v 點的最短距離。對於圖G 上的點對( u, v) ,若它們的距離為2 ,則它們之間會產生Wu×Wv 的聯合權值。

請問圖G 上所有可產生聯合權值的有序點對中,聯合權值最大的是多少?所有聯合權值之和是多少?

思路:註意題目中這是一個無向連通圖,且被n-1條邊連著,這讓我們想起什麽呢,這就是一個樹,而且退化成了一條鏈。所以我們只要枚舉每個點,然後跟他連著的點的權值相乘就好了,最後還要乘以二,因為題目中要求我們求a—b&&b—a(就這麽簡單,懶得敲代碼,上網找了一篇,放心,我會給你們註釋的很明白的

 1 #include<cstdio>
 2 #include<cmath>
 3 using namespace std;
 4 struct Edge
 5 {
 6     int t,nexty;
 7 }edge[1000000];//鏈式前向星,不明白的沒關系我可能已經發表了關於鏈式前向星的博客,請前去看看
 8 int head[300000]={0},cnt=0;//關於建圖
 9 void add(int a,int b)
10 {
11     cnt++;
12     edge[cnt].t=b,edge[cnt].nexty=head[a];
13     head[a]=cnt;
14 } 15 long long w[300000]={0};//w數組代表點的值 16 int main() 17 { 18 int n;//n個點 19 scanf("%d",&n);//輸入 20 int a,b;//a點,b點 21 for(int i=0;i<n-1;i++) 22 { 23 scanf("%d%d",&a,&b);//輸入a,b倆點 24 add(a,b),add(b,a);//a,b倆點之間建邊 25 } 26 for(int i=1;i<=n;i++)scanf("%lld",&w[i]);//輸入點的值
27 long long sum=0,maxn=0;//sum記錄著聯合權值的總和,maxn記錄最大值的聯合權值 28 long long he,rmax;//he表示當前的和,rmax是指當前的最大值 29 int node;//後面領悟吧,不好說,可以換掉這個 30 for(int i=1;i<=n;i++) 31 { 32 node=head[i];//這關 33 he=(rmax=w[edge[node].t])%10007;//此時的he要等於他的一條邊連這那個點的值 34 node=edge[node].nexty;//換另一條邊 35 for(;node!=0;node=edge[node].nexty)//核心代碼,後方高能 36 { 37 sum=(sum+he*w[edge[node].t])%10007;//總和要加上聯合權值的和 38 maxn=max(maxn,rmax*w[edge[node].t]);//最大值要與此時的最大值進行比較 39 he=(he+w[edge[node].t])%10007;//和要加上第二條邊所連點的值 40 rmax=max(rmax,w[edge[node].t]);//rmax進行更新 41 } 42 } 43 printf("%lld %lld",maxn,(sum*2)%10007);//輸出 44 return 0; 45 }

luoguP1351 聯合權值