① 兩次dfs
方法:先從任意一點P出發,找離它最遠的點Q,再從點Q出發,找離它最遠的點W,W到Q的距離就是是的直徑
證明如下:
①若P已經在直徑上,根據樹的直徑的定義可知Q也在直徑上且為直徑的一個端點
②若P不在直徑上,我們用反證法,假設此時WQ不是直徑,AB是直徑
--->若AB與PQ有交點C,由於P到Q最遠,那么PC+CQ>PC+CA,所以CQ>CA,易得CQ+CB>CA+CB,即CQ+CB>AB,與AB是直徑矛盾,不成立,如下圖(其中AB,PQ不一定是
直線,畫成直線是為了方便):

--->若AB與PQ沒有交點,M為AB上任意一點,N為PQ上任意一點。首先還是NP+NQ>NQ+MN+MB,同時減掉NQ,得NP>MN+MB,易知NP+MN>MB,所NP+MN+MA>MB+MA,
即NP+MN+MA>AB,與AB是直徑矛盾,所以這種情況也不成立,如下圖:

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 100000 6 using namespace std; 7 inline int read() 8 { 9 int x=0; 10 bool f=1; 11 char c=getchar(); 12 for(; !isdigit(c); c=getchar()) if(c=='-') f=0; 13 for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0'; 14 if(f) return x; 15 return 0-x; 16 } 17 struct node 18 { 19 int u,v,w,nex; 20 }edge[2*maxn+10]; 21 int n,m,d[maxn+10],head[maxn+10],f_num,cnt=0,ans; 22 inline void add(int x,int y,int z) 23 { 24 cnt++; 25 edge[cnt].u=x; 26 edge[cnt].v=y; 27 edge[cnt].w=z; 28 edge[cnt].nex=head[x]; 29 head[x]=cnt; 30 } 31 inline void dfs(int x,int fa) 32 { 33 if(ans<d[x]) 34 { 35 ans=d[x]; 36 f_num=x; 37 } 38 for(int i=head[x];i!=-1;i=edge[i].nex) 39 { 40 int j=edge[i].v; 41 if(j==fa)continue; 42 d[j]=d[x]+edge[i].w; 43 dfs(j,x); 44 } 45 } 46 int main() 47 { 48 memset(head,-1,sizeof(head)); 49 n=read();m=read(); 50 for(int i=1;i<=m;i++) 51 { 52 int x,y,z; 53 x=read();y=read();z=read(); 54 add(x,y,z); 55 add(y,x,z); 56 } 57 dfs(1,0); 58 ans=0; 59 d[f_num]=0; 60 dfs(f_num,0); 61 printf("%d",ans); 62 return 0; 63 }
② 樹形DP
對於每個節點我們要記錄兩個值:f1 [ i ] 表示以 i 為根的子樹中,i 到葉子結點距離的最大值f2 [ i ] 表示以 i 為根的子樹中,i 到葉子結點距離的次大值對於一個節點,它到葉子結點距
離的最大值和次大致所經 過的路徑肯定是不一樣的若j是i的兒子,那么(下面的 w [ i ][ j ] 表示 i 到 j 的路徑長度):
若 f1 [ i ] < f1 [ j ] + w [ i ][ j ],f2 [ i ] =f1 [ i ],f1 [ i ] = f1 [ j ] + w [ i ][ j ];
否則,若 f2 [ i ] < f1 [ j ] + w [ i ][ j ],f2 [i ] = f1 [ j ] + w [ i ][ j ];
理解:這樣做就是,先看能否更新最大值,若能,它的次大值就是原先的最大值,再更新它的最大值;若不能,就看能不能更新次大值,若能,就更新,不能就不管它
這樣的話,最后的答案 answer = max { f1 [ i ] + f2[ i ] }
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 100000 6 #define INF 2147483647/2-1 7 using namespace std; 8 inline int read() 9 { 10 int x=0; 11 bool f=1; 12 char c=getchar(); 13 for(; !isdigit(c); c=getchar()) if(c=='-') f=0; 14 for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0'; 15 if(f) return x; 16 return 0-x; 17 } 18 int n,m,ans,f1[maxn+10],f2[maxn+10],head[maxn+10],cnt=0; 19 struct node 20 { 21 int u,v,w,nex; 22 }edge[2*maxn+10]; 23 inline void add(int x,int y,int z) 24 { 25 cnt++; 26 edge[cnt].u=x; 27 edge[cnt].v=y; 28 edge[cnt].w=z; 29 edge[cnt].nex=head[x]; 30 head[x]=cnt; 31 } 32 inline void dp(int x,int fa) 33 { 34 for(int i=head[x];i!=-1;i=edge[i].nex) 35 { 36 int j=edge[i].v; 37 if(j==fa)continue; 38 dp(j,x); 39 if(f1[x]<f1[j]+edge[i].w) 40 { 41 f2[x]=f1[x]; 42 f1[x]=f1[j]+edge[i].w; 43 } 44 else if(f2[x]<f1[j]+edge[i].w) 45 { 46 f2[x]=f1[j]+edge[i].w; 47 } 48 ans=max(ans,f1[x]+f2[x]); 49 } 50 } 51 int main() 52 { 53 memset(head,-1,sizeof(head)); 54 n=read();m=read(); 55 for(int i=1;i<=m;i++) 56 { 57 int x,y,z; 58 x=read();y=read();z=read(); 59 add(x,y,z); 60 add(y,x,z); 61 } 62 dp(1,0); 63 printf("%d",ans); 64 return 0; 65 }
原文作者:forever_dreams 來源:CSDN
請各位大佬斧正(反正我不認識斧正是什么意思)
