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

Highway
Accepted : 33           Submit : 137
Time Limit : 4000 MS           Memory Limit : 65536 KB

Highway

In ICPCCamp there were n towns conveniently numbered with 1,2,…,n connected with (n−1) 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 (n−1) 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 (n−1) 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 (n−1) lines contains three integers ai, bi and ci.

    1≤n≤105
    1≤ai,bi≤n
    1≤ci≤108
    The number of test cases does not exceed 10.

Output

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

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

Sample Output

19
15


Source

XTU OnlineJudge

题目大意:

给出一棵无根树,给出n-1条边和权值,然后让你求重新选择n-1条边使其联通并且权和最大

题目思路: 这道题就是让你求对于i点,距离这个点最远的店,我们容易想到用dp写,但是这样明显有一个问题,就是会不会有重复的,还需要标记一下,有点麻烦,但是

其实我们不用担心这个,接下来我们引入树的直径的概念,并给出一些推论,树的直径是指树上权值和最大的路径(最简单路径,即每一个点只经过一次),存在结论:对于树上的任意一个一个节点,距离这个节点最远的距离一定是直径的两个端点,给出证明:假设当前点为u,直径端点为s,t,第一种情况:u在直径上,那么显然终点在端点上,我们用反证法证明,假设终点不在端点上,设其为e,那么存在dis(u-e)大于dis(u-s) 即存在dis(u-e)+dis(u-t)>dis(u-s)+dis(u-s)=dis(u-t)矛盾

第二种情况:u不在直径上

第一种情况,当u的最长路与直径相交,设交点为x,此时存在,dis(u-x)+dis(x-e)>dis(u-x)+dis(x-s) 即dis(u-x)+dis(x-e)+dis(x+t)>dis(u-x)+dis(x-s)+dis(x-t) = dis(u-x) +dis(s-t)矛盾,

第二种情况:不想交,这种麻烦点懒得推了

说一下求端点的技巧,选取任意一点开始dfs,去到的权值和最大的即为端点之一,然后从这个端点开始出发去寻找另一个端点

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<iostream>
#include<sstream>
#include<string>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e5+10;
int head[maxn*2];
int erear;
LL dS[maxn*2];
LL dT[maxn*2];
struct node
{
    LL x,to,cost,next;
}E[maxn*2];
int n;
void __init__()
{
    memset(head,-1,sizeof(head));
    memset(dS,0,sizeof(dS));
    memset(dT,0,sizeof(dT));
    erear = 0;
}
void build(LL x,LL y ,LL cost)
{
    E[erear].x = x;
    E[erear].to = y;
    E[erear].cost = cost;
    E[erear].next = head[x];
    head[x] = erear++;
}
void dfs1(LL u,LL &S,LL f)
{
    if(dS[u]>dS[S]) S = u;
    for(LL i = head[u];i!=-1;i = E[i].next)
    {
        LL to = E[i].to;
        if(to==f)
            continue;
        dS[to] = dS[u]+E[i].cost;
        dfs1(to,S,u);
    }
}
void dfs2(LL u,LL fa,LL d[])
{
    for(LL i = head[u];i != -1;i=E[i].next)
    {
        int to = E[i].to;
        if(to==fa)
            continue;
        d[to] = d[u] + E[i].cost;
        dfs2(to,u,d);
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        __init__();
        for(int i = 0 ;i<n-1;i++)
        {
            LL x,y,cost;
            scanf("%lld%lld%lld",&x,&y,&cost);
            build(x,y,cost);
            build(y,x,cost);
        }
        LL S,T;
        S = 1;
        dfs1(1,S,-1);
        T = S;
        dS[S] = 0;
        dfs1(S,T,-1);
        dfs2(S,-1,dS);
        dfs2(T,-1,dT);
        LL ans = 0;
        for(int i = 1;i<=n;i++)
        {
            ans += max(dS[i],dT[i]);
        }
        cout<<ans-dS[T]<<endl;
        //cout<<"\\n"<<endl;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值