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
#include
#include
#include
#include
#include
#include
#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


你可能感兴趣的:(dp,数据结构,ACM,dp,数据结构)