洛谷P1099树网的核

求树的直径,然后保存直径的端点,然后枚举路径上的点

//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int inf=99999999;
int dis[1001][1001]; 
int fr[1001],to[1001];
int m,n,cnt;
int maxn=0;
inline int read()
{
	int x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
} 
inline void floyd()
{
	for (int k=1;k<=n;k++)
	for (int i=1;i<=n;i++)
	for (int j=1;j<=n;j++)
		dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
    return ;
}
inline void getdia()
{
	for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
		if(dis[i][j]!=inf)
        	maxn=max(maxn,dis[i][j]);
    for (int i=1;i<=n;i++)
	for (int k=1;k<=n;k++)
    if(maxn==dis[i][k])
        fr[++cnt]=i,to[cnt]=k;
	return ;
}
inline void simul()
{
    int minn=inf;
	for (int i=1;i<=n;i++)
    for (int j=1;j<=n;j++)
    {
        int ans=0;
        for (int l=1;l<=cnt;l++)
        if(dis[i][j]!=inf&&dis[i][j]<=m&&dis[fr[l]][i]+dis[i][j]+dis[j][to[l]]==maxn)
        {
            for (int k=1;k<=n;k++)
            {
                if(k!=i&&k!=j)
                ans=max(ans,(dis[k][i]+dis[k][j]-dis[i][j])/2);
            }
            minn=min(minn,ans);
		}
	}
	return (void)(cout<<minn);
}
int main()
{
	n=read();m=read(); 
    for (int i=1;i<=n;i++)
    for (int k=1;k<=n;k++)
    if (i!=k) dis[i][k]=inf;
	else dis[i][k]=0;
    for (int i=1;i<n;i++)
	{
		int a=read(),b=read(),c=read();
		dis[a][b]=c;dis[b][a]=c;
	}
    floyd();getdia();simul();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/acerandaker/article/details/80954672