树网的核

树网的核


这一题,刚开始看题目感觉好像很难,题目又长……一看数据范围,呵呵。

已经给出来这是个DAG,所以不用担心连通性的问题。那么怎么做呢?

朴素的做法是把树的直径的两个端点都统计出来,然后暴力算那个什么偏心距,这里可以用floyd预处理,反正才n才300。还有一点,怎么算一个点到一条路径的距离呢,很简单,计算点到路径的距离,由于这是一张树网,且已经预处理点对之间的距离,从而点k到路径(i,j)的距离即为

(dist[k][i]+dist[k][j]-dist[i][j])/2   //可以画图理解一下,注意是没有环的。
然后就开始敲了,但后来发现好像不用管直径,只用枚举一条路径就行了(满足最优的路径一定在树的直径上)

时间复杂度嘛……O(n^3)

上代码:

#include<bits/stdc++.h>
using namespace std;
const int inf=99999999;
const int N = 305;
int n,m,a[N][N],ans=inf,dis,u,v,c;
int main()
{
 	scanf("%d%d",&n,&m);
 	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++) if(i-j) a[i][j]=inf;
 	for(int i=1;i<n;i++){
 		scanf("%d%d%d",&u,&v,&c);
 		a[u][v]=a[v][u]=c;
	 }
   for(int k=1;k<=n;k++)
	 for(int i=1;i<=n;i++)
	    for(int j=1;j<=n;j++)
	       a[i][j]=min(a[i][k]+a[k][j],a[i][j]);//标准floyd
        //枚举路径i->j,和点k。不用判断a[i][j]为inf,因为图是双向联通的。
	for(int i=1;i<=n;i++){
		for(int j=i;j<=n;j++)if(a[i][j]<=m){
			dis=0;
			for(int k=1;k<=n;k++){
				dis=max(dis,(a[k][i]+a[k][j]-a[i][j])/2);
			}
			ans=min(dis,ans);			
		}
	}
	printf("%d",ans);
   return 0;
}
是不是很短!

猜你喜欢

转载自blog.csdn.net/qq_38944163/article/details/80723921