题目描述
题解
这一题,刚开始看题目感觉好像很难,题目又长……一看数据范围,呵呵。
已经给出来这是个DAG,所以不用担心连通性的问题。那么怎么做呢?
朴素的做法是把树的直径的两个端点都统计出来,然后暴力算那个什么偏心距,这里可以用floyd预处理,反正才n才300。还有一点,怎么算一个点到一条路径的距离呢,很简单,计算点到路径的距离,由于这是一张树网,且已经预处理点对之间的距离,从而点k到路径(i,j)的距离即为
1 (dist[k][i]+dist[k][j]-dist[i][j])/2 //可以画图理解一下,注意是没有环的。
然后就开始敲了,但后来发现好像不用管直径,只用枚举一条路径就行了(满足最优的路径一定在树的直径上)
时间复杂度嘛……O(n^3)
参考代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int inf=1e9; 4 const int N=305; 5 int n,m,a[N][N],ans=inf,dis,u,v,c; 6 int main() 7 { 8 scanf("%d %d",&n,&m); 9 for(int i=1;i<=n;i++) 10 { 11 for(int j=1;j<=n;j++) 12 { 13 if(i-j) 14 a[i][j]=inf; 15 } 16 } 17 for(int i=1;i<n;i++) 18 { 19 scanf("%d%d%d",&u,&v,&c); 20 a[u][v]=a[v][u]=c; 21 } 22 for(int k=1;k<=n;k++) 23 { 24 for(int i=1;i<=n;i++) 25 { 26 for(int j=1;j<=n;j++) 27 a[i][j]=min(a[i][k]+a[k][j],a[i][j]); 28 } 29 } 30 for(int i=1;i<=n;i++) 31 { 32 for(int j=i;j<=n;j++) 33 { 34 if(a[i][j]<=m) 35 { 36 dis=0; 37 for(int k=1;k<=n;k++) 38 { 39 dis=max(dis,(a[k][i]+a[k][j]-a[i][j])/2); 40 } 41 ans=min(dis,ans); 42 } 43 } 44 } 45 printf("%d",ans); 46 return 0; 47 }