zoukankan      html  css  js  c++  java
  • 2017湘潭大学邀请赛H题(树的直径)

     链接:https://www.icpc.camp/contests/4mYguiUR8k0GKE

                                                     H. Highway

    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.

    题意:

        每次连接最远的两点,直到所有点都相通。

         最多有n-1条边

    题解:

         如何每次都找到最远的两个点呢?

    我们需要用到一个定理:树上的任何一个点的最远点一定会是<树的直径>中的一个

    树的直径指:树上的最远的两个点

    接下来我们证明这个定理——

    1,利用这个定理,我们可以从<1节点>dfs找到一个直径上的点。

    2,用直径上的这个点dfs可以找到另外一个直径上的点。

    3,找出所有点到这两个直径上的点的距离

    4,将所有点都连接在直径的两个点之一,就是答案了

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+5;
    int f[maxn],nex[2*maxn],w[2*maxn],tob[2*maxn],inde;
    long long  dis1[maxn],dis2[maxn];
    bool vis[maxn];
    long long  s1,maxdis,s2;
    long long  madis=-1;
    void add(int a,int b,int wn)
    {
        inde++;
        tob[inde]=b;
        w[inde]=wn;
        nex[inde]=f[a];
        f[a]=inde;
    }
    void dfs1(int x,long long  v)
    {
        vis[x]=0;
        for(int i=f[x];i;i=nex[i])
        {
            if(vis[tob[i]])
            {
                long long  gg=v+w[i];
                if(gg>madis)
                {
    
                    madis=gg;
                    s1=tob[i];
                }
                dfs1(tob[i],gg);
            }
        }
    }
    void dfs2(int x,long long v)
    {
         vis[x]=0;
        for(int i=f[x];i;i=nex[i])
        {
            if(vis[tob[i]])
            {
                long long gg=v+w[i];
                if(gg>maxdis)
                {
                    maxdis=gg;
                    s2=tob[i];
                }
                dis1[tob[i]]=gg;
                dfs2(tob[i],gg);
            }
        }
    }
    void dfs3(int x,long long  v)
    {
        vis[x]=0;
        for(int i=f[x];i;i=nex[i])
        {
            if(vis[tob[i]])
            {
                long long gg=v+w[i];
                dis2[tob[i]]=gg;
                dfs3(tob[i],gg);
            }
        }
    }
    int main()
    {
        int n;
        while(cin>>n)
        {
            inde=0;
            for(int i=1;i<=n;i++)f[i]=0;
            for(int i=1;i<n;i++)
            {
                int a,b,wn;
                scanf("%d %d %d",&a,&b,&wn);
                add(a,b,wn);
                add(b,a,wn);
            }
            maxdis=madis=-1;
            for(int i=1;i<=n;i++)vis[i]=1;
            dfs1(1,0);
            for(int i=1;i<=n;i++)vis[i]=1;
            dfs2(s1,0);
            for(int i=1;i<=n;i++)vis[i]=1;
            dfs3(s2,0);
            long long  ans=maxdis;
            for(int i=1;i<=n;i++)
            {
                if(i==s1||i==s2)continue;
                ans+=max(dis1[i],dis2[i]);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    

      

  • 相关阅读:
    mongodb MongoDB 聚合 group
    mongo数据库的各种查询语句示例
    Web测试方法总结
    python + selenium 自动化测试框架
    selenium关于断言的使用
    JavaScript利用键盘方向键(上下键)控制表格行选中
    TestNG 入门教程
    selenium+python之 辨识alert、window以及操作
    Selenium WebDriver中鼠标事件
    JS-运动基础(一)
  • 原文地址:https://www.cnblogs.com/carcar/p/9023117.html
Copyright © 2011-2022 走看看