ccpc湘潭邀请赛 h-highway(树的直径)

Highway

Accepted : 141 Submit : 488
Time Limit : 4000 MS Memory Limit : 65536 KB 

Highway

In ICPCCamp there were  n  towns conveniently numbered with  1,2,,n  connected with  (n1)  roads. The  i -th road connecting towns  ai  and  bi  has length  ci . It is guaranteed that any two cities reach each other using only roads.

Bobo would like to build  (n1)  highways so that any two towns reach each using only highways. Building a highway between towns  x  and  y  costs him  δ(x,y)  cents, where  δ(x,y)  is the length of the shortest path between towns  x  and  y  using roads.

As Bobo is rich, he would like to find the most expensive way to build the  (n1)  highways.

Input

The input contains zero or more test cases and is terminated by end-of-file. For each test case:

The first line contains an integer  n . The  i -th of the following  (n1)  lines contains three integers  ai bi  and  ci .

  • 1n105
  • 1ai,bin
  • 1ci108
  • The number of test cases does not exceed  10 .

Output

For each test case, output an integer which denotes the result.


题目链接:http://202.197.224.59/OnlineJudge2/index.php/Contest/read_problem/cid/43/pid/1267

说实话,当时没读懂这题的意思,对于树的直径这个概念也是一无所知

官方题解: 
这里写图片描述

关于树的直径 
树的直径是指树上权值和最大的路径(最简单路径,即每一个点只经过一次,也就是最大生成树) 
存在结论:对于树上的任意一个节点,距离这个节点最远的距离一定是到直径的端点的距离;

由于只有(n-1)条边,直接dfs找最大生成树即可

先从任意一个点dfs找出距离其最远的点d1,则d1一定为树的直径的一个端点;

然后由d1出发找到距离其最远的点d2,则d2为树的直径的另一个端点,保存路径上所有点到d1的距离,最后会用到;

最后由d2向的搜索,保存路径上所有点到d2的距离;

由于d1到d2一定为最远,直接加上,其他点加上max(到d1距离,到d2距离),即可求出最大花费;

#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define wtf printf("wtf\n");
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define N 100010
#define ll long long
using namespace std;
int n,len;
bool vis[N];
ll disd1[N],disd2[N];
int first[N];
struct node
{
    int to,nex;
    ll w;
}e[N<<1];
void dfs(int st,ll len,ll dis[])
{
    vis[st]=true;
    dis[st]=len;
    for(int i=first[st];~i; i=e[i].nex)
    {
        if(!vis[e[i].to])
        {
            dfs(e[i].to,len+e[i].w,dis);
        }
    }
}
void add_edge(int u,int v,ll w)
{
    e[len].to=v;
    e[len].w=w;
    e[len].nex=first[u];
    first[u]=len++;
}
int main()
{
    while(~scanf("%d",&n))
    {
        int u,v,w;
        len=0;
        mem(disd1,0);
        mem(disd2,0);
        mem(first,-1);
        for(int i=1; i<n; i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            add_edge(u,v,w);
            add_edge(v,u,w);
        }
        mem(vis,false);
        ll maxx=0;
        dfs(1,0,disd1);
        int d1,d2;
        for(int i=1; i<=n; i++)
        {
            if(maxx<disd1[i])
            {
                maxx=disd1[i];
                d1=i;
            }
        }
        mem(vis,false);
        dfs(d1,0,disd1);
        maxx=0;
        for(int i=1; i<=n; i++)
        {
            if(maxx<disd1[i])
            {
                maxx=disd1[i];
                d2=i;
            }
        }
         mem(vis,false);
        dfs(d2,0,disd2);
       ll ans=disd1[d2];
       for(int i=1;i<=n;i++)
       {
           if(i!=d1&&i!=d2)
           {
               ans+=max(disd1[i],disd2[i]);
           }
       }
       printf("%I64d\n",ans);
    }
}

参考博客: Alzh

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值