acwing 1073 树的中心

题意:

给定一棵树,树中包含 n 个结点(编号1~n)和 n−1 条无向边,每条边都有一个权值。

请你在树中找到一个点,使得该点到树中其他结点的最远距离最近。

输入格式

第一行包含整数 n。

接下来 n−1 行,每行包含三个整数 ai,bi,ci,表示点 ai 和 bi 之间存在一条权值为 ci 的边。

输出格式

输出一个整数,表示所求点到树中其他结点的最远距离。

数据范围

1≤n≤10000
1≤ai,bi≤n
−1e5≤ci≤1e5

输入样例:

5 
2 1 1 
3 2 1 
4 3 1 
5 1 1

输出样例:

2

 题解:

       把1当成树根,  每个节点到其余点的最远距离可以分为两部分去计算,当前节点往下走的最远距离,当前节点往上走的最远距离,然后这两个距离取最大值。

     第一次dfs  计算往下走的最远距离,可以进行一次dfs,在回溯的时候由子节点更新当前节点,相当于从下往上更新。

       第二次dfs 计算往上走的最远距离,当前节点y往上走的最远距离肯定是由当前节点的父节点x转移过来。至于怎么转移,我们画一个树的图能够发现,由其余点到(除了y到x的分支)父节点x的最远距离加上x到y的最远距离。 更新这个距离需要在第一次dfs的时候记录一下x节点往下走的次远距离。

    具体实现看代码。

求出每个点到其余点的最远距离,然后所有的最远距离求最小值就是答案。

代码:

#include
using namespace std;
typedef long long ll;
const int maxn=10005;
const int inf=0x3f3f3f3f;
int f[maxn],ff[maxn];   //f[i]记录i往下走的最远距离,ff[i]记录i往下走的次远距离
int fff[maxn]; //fff[i]记录i往上走的最远距离
int head[maxn],nex[maxn*2],to[maxn*2],w[maxn*2],cnt;
int n;
void add(int i,int j,int k){
    cnt++;
    to[cnt]=j;w[cnt]=k;nex[cnt]=head[i];head[i]=cnt;
}
void dfs(int x,int fa){
    f[x]=ff[x]=-inf;
    for(int i=head[x];i;i=nex[i]){
        int y=to[i];
        if(y==fa) continue;
        dfs(y,x);
        if(f[y]+w[i]>f[x]){
            ff[x]=f[x];
            f[x]=f[y]+w[i];
        }else if(f[y]+w[i]>ff[x]){
            ff[x]=f[y]+w[i];
        }
    }
    if(f[x]==-inf){
        f[x]=0;
    }
    if(ff[x]==-inf){
        ff[x]=0;
    }
}
void dfs2(int x,int fa){
    for(int i=head[x];i;i=nex[i]){
        int y=to[i];
        if(y==fa) continue;
        int maxx;
        if(f[y]+w[i]!=f[x]) maxx=f[x];
        else maxx=ff[x];
        maxx=max(maxx,fff[x]);
        fff[y]=max(fff[y],maxx+w[i]);
        dfs2(y,x);
    }
}
int main(){
    memset(fff,-0x3f,sizeof fff);
    scanf("%d",&n);
    for(int i=1;i

    

你可能感兴趣的:(搜索)