1. 程式人生 > >【tyvj1520】 樹的直徑

【tyvj1520】 樹的直徑

with 樹上最長鏈 mes for 一個數 sizeof names 格式 整數

描述 Description

樹的直徑,即這棵樹中距離最遠的兩個結點的距離。每兩個相鄰的結點的距離為1,即父親結點與兒子結點或兒子結點與父子結點之間的距離為1.有趣的是,從樹的任意一個結點a出發,走到距離最遠的結點b,再從結點b出發,能夠走的最遠距離,就是樹的直徑。樹中相鄰兩個結點的距離為1。你的任務是:給定一棵樹,求這棵樹中距離最遠的兩個結點的距離。

輸入格式 InputFormat

輸入共n行
第一行是一個正整數n,表示這棵樹的結點數
接下來的n-1行,每行三個正整數a,b,w。表示結點a和結點b之間有一條邊,長度為w
數據保證一定是一棵樹,不必判錯。

輸出格式 OutputFormat

輸出共一行
第一行僅一個數,表示這棵樹的最遠距離

樣例輸入 SampleInput

4
1 2 10
1 3 12
1 4 15

樣例輸出 SampleOutput

27

數據範圍和註釋 Hint

10%的數據滿足1<=n<=5
40%的數據滿足1<=n<=100
100%的數據滿足1<=n<=10000 1<=a,b<=n 1<=w<=10000

題解

此題求樹上最長鏈,即樹的直徑,有很多方法 可以如題中所說,用兩次bfs,求出1的最遠點X,再求X的最遠點Y,XY即為直徑 這個證明比較容易,大致可以分三步 先證明1,X一定和直徑有交 再證明X一定是直徑的一個端點 那麽找X的最遠點Y,XY即為直徑 或者可以采用dp做法,基於直徑為某個點到其不同子樹葉子的最長鏈+次長鏈 BFS
 1
#include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 #define ll long long 7 using namespace std; 8 ll read(){ 9 int x=0,f=1;char ch=getchar(); 10 while(ch<0||ch>9){ if(ch==-)f=-1;ch=getchar();} 11
while(ch>=0&&ch<=9){ x=x*10+ch-0;ch=getchar();} 12 return x*f; 13 } 14 int X,n,q[100005],d[100005]; 15 vector<int> e[100005],len[100005]; 16 char ch[5]; 17 void bfs(int x){ 18 X=0; 19 int head=0,tail=1; 20 q[0]=x; 21 memset(d,0,sizeof(d)); 22 while(head!=tail){ 23 int now=q[head];head++; 24 if(d[now]>d[X]) X=now; 25 for(int i=0;i<e[now].size();i++){ 26 if(!d[e[now][i]]&&e[now][i]!=x){ 27 d[e[now][i]]=d[now]+len[now][i]; 28 q[tail++]=e[now][i]; 29 } 30 } 31 } 32 } 33 int main(){ 34 n=read(); 35 for(int i=1;i<n;i++){ 36 int u=read(),v=read(),w=read(); 37 e[u].push_back(v); len[u].push_back(w); 38 e[v].push_back(u); len[v].push_back(w); 39 } 40 bfs(1); bfs(X); 41 printf("%d\n",d[X]); 42 return 0; 43 }

DP

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #define maxn 10005
 6 #define inf 0x7fffffff
 7 using namespace std;
 8 int n,cnt,ans;
 9 int f1[maxn],f2[maxn],last[maxn];  //f1求最長鏈,f2求次長鏈
10 struct edge{
11     int to,next,v;
12 }e[maxn<<1];
13 void add(int u,int v,int w){
14     e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w;
15 }
16 void dp(int x,int fa){
17     for(int i=last[x];i;i=e[i].next){
18         int y=e[i].to;
19         if(y==fa) continue;
20         dp(y,x);
21         if(f1[y]+e[i].v>f1[x]){
22             f2[x]=f1[x];
23             f1[x]=f1[y]+e[i].v;
24         }
25         else f2[x]=max(f2[x],f1[y]+e[i].v);
26     }
27     ans=max(f1[x]+f2[x],ans);
28 }
29 int main(){
30     ios::sync_with_stdio(false);
31     cin>>n;
32     for(int i=1;i<n;i++){
33         int u,v,w;
34         cin>>u>>v>>w;
35         add(u,v,w); add(v,u,w);
36     }
37     dp(1,0);
38     cout<<ans<<endl;
39     return 0;
40 }

【tyvj1520】 樹的直徑