1. 程式人生 > >樹的直徑 NOIP 2007 樹網的核

樹的直徑 NOIP 2007 樹網的核

題意:求一條直徑上的鏈,要求鏈長<=s<=s,使所有點到這條鏈上的距離中的最大值最小。

首先我們先求出直徑,年輕的時候n3n^3求直徑也是沒誰了qwq 首先若直徑<=s<=s,我們列舉所有一個在直徑上,一個在直徑外的點對,他們距離的最小值就是答案。 若直徑>s>s,我們列舉直徑上的兩點,有定理:對於直徑上任意一個點,到它本身的距離最遠的點一定是直徑的某個端點。所以答案就是 max(min(e[i][l],e[l][j]),min(e[i][r],e[j][r]));l,r

,i,jmax(min(e[i][l],e[l][j]),min(e[i][r],e[j][r]));,l,r為直徑的兩端點,i,j為直徑上的點對 的最小值。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int INF=999999999;
int e[1000][1000];
int n,
s; int main() { cin>>n>>s; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) { if(i!=j) e[i][j]=INF; else e[i][j]=0; } for(int i=1;i<=n-1;++i) { int u,v,d; scanf("%d%d%d",&
u,&v,&d); e[u][v]=d; e[v][u]=d; } for(int k=1;k<=n;++k) for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(e[i][j]>e[i][k]+e[k][j]) e[i][j]=e[i][k]+e[k][j]; int l,r,maxx=0; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) { if(e[i][j]!=INF&&e[i][j]>maxx) { l=i; r=j; maxx=e[i][j]; } } int ans=INF; int maxxx=0; if(e[l][r]<=s) { for(int i=1;i<=n;++i) if(e[l][i]+e[i][r]==e[l][r]) for(int j=1;j<=n;++j) if(e[l][j]+e[j][r]!=e[l][r]) ans=min(e[i][j],ans); cout<<ans; } else { for(int i=1;i<=n;++i) if(e[l][i]+e[i][r]==e[l][r]) for(int j=1;j<=n;++j) if(e[l][j]+e[j][r]==e[l][r]) { if(e[i][j]>s) continue; maxxx=max(min(e[i][l],e[l][j]),min(e[i][r],e[j][r])); ans=min(ans,maxxx); } cout<<ans; } return 0; }