树的直径 NOIP 2007 树网的核

版权声明:未经本蒟蒻同意,请勿转载本蒻博客 https://blog.csdn.net/wddwjlss/article/details/83178279

题意:求一条直径上的链,要求链长 < = s <=s ,使所有点到这条链上的距离中的最大值最小。

首先我们先求出直径,年轻的时候 n 3 n^3 求直径也是没谁了qwq
首先若直径 < = s <=s ,我们枚举所有一个在直径上,一个在直径外的点对,他们距离的最小值就是答案。
若直径 > s >s ,我们枚举直径上的两点,有定理:对于直径上任意一个点,到它本身的距离最远的点一定是直径的某个端点。所以答案就是
m a x ( m i n ( e [ i ] [ l ] , e [ l ] [ j ] ) , m i n ( e [ i ] [ r ] , e [ j ] [ r ] ) ) ; l , r , i , j max(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;
}

猜你喜欢

转载自blog.csdn.net/wddwjlss/article/details/83178279
今日推荐