zoukankan      html  css  js  c++  java
  • HDU 3721 Building Roads(树的中心)


    3721 Building Roads

      Time Limit:16000/8000 MS (Java/Others)
      Memory Limit: 32768/32768 K (Java/Others)

    Description###

      There is a magic planet in the space. There is a magical country on the planet. There are N cities in the country. The country is magical because there are exactly N-1 magic roads between the N cities, and from each city, it is possible to visit any other city. But after the huge expansion of the country, the road system seems to be messy. The moderator decided to rebuild the road system.
    As a worker, I cannot do too much things. I could just move one road to another position connecting arbitrary 2 cities using my magic, keeping its length unchanged. Of course, afterwards all the N cities have to be still connected. I wonder how to move in order to make the farthest distance between any two cities minimum. Could you solve it for me?
       

    Input###

      The first line of the input is one integer T (T ≤ 10), and then T test cases follow.
    Each test case begins with a line contains only one integer N (N ≤ 2500), means there are N magic cities. The cities are numbered from 0 to N-1.
    Following N-1 lines, each line has 3 integers a, b and c, means there is a magic road between a and b with distance c. (0 <= a, b < N, 0 < c <= 1000)
      

    Output###

      For each test case, output the case number and the corresponding minimum >farthest distance. See sample for detailed format.
      

    Sample Input 1###

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

    Sample Output 1###

      Case 1: 4
      Case 2: 7

    HINT###

      

    题目地址: HDU 3721 Building Roads

    题解:

         
      题目大意:一棵树断掉一条边,用此边再连接两个点,使得还是一棵树,且使任意两个点之间的最远距离最小,求此距离
      要求即为直径最小
      枚举断边,分成两棵树,连边的两个端点分别在两棵树上,考虑连哪两个点
      树的中心:这个点到树的其他结点的最远距离最近
      显然就是连两棵树的中心了,那么如何求树的中心
      d1[u]表示以u为根的子树中,u到叶子结点距离的最大值,用s1[u]记录该叶子结点
      d2[u]表示以u为根的子树中,u到叶子结点距离的次大值
      up[u]表示树中除了以u为根的子树中的叶子结点外,其他的叶子结点到u的最大值
      这些都非常好求
      树的中心即为T[u]=max(d1[u],up[u])最小的点
      两棵树合并后的直径有三种情况:树1的直径,树2的直径,两个中心的T[u]相加+删掉边的长度
    www.cnblogs.com/AGFghy/


    AC代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    int n,Q,num,d,ans1,ans2,ans;
    int head[3005],Next[6005],point[6005],len[6005];
    int a[5],u[3005],v[3005],l[3005],up[3005],d1[3005],d2[3005],s1[3005],belong[3005];
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void add(int u,int v,int l)
    {
        point[++num]=v;
        len[num]=l;
        Next[num]=head[u];
        head[u]=num;
    }
    void dfs1(int now,int pre,int kd)
    {
        belong[now]=1-kd;
        for (int i=head[now]; i; i=Next[i])
        {
            int v=point[i];
            if (v==pre||v==a[kd]) continue;
            dfs1(v,now,kd);
            if (d1[now]<d1[v]+len[i])
            {
                d2[now]=d1[now]; 
                d1[now]=d1[v]+len[i]; s1[now]=v;
            }
            else
            if (d2[now]<d1[v]+len[i]) d2[now]=d1[v]+len[i];
        }
    }
    void dfs2(int now,int pre,int kd)
    {
        for (int i=head[now]; i; i=Next[i])
        {
            int v=point[i];
            if (v==pre||v==a[kd]) continue;
            if (v!=s1[now]) up[v]=max(up[now],d1[now])+len[i];
            else up[v]=max(up[now],d2[now])+len[i];
            dfs2(v,now,kd);
        }
    }
    int main()
    {
        Q=read(); 
        for (int cas=1; cas<=Q; cas++)
        {
            n=read();
            num=0;
            for (int i=1; i<=n; i++)
                head[i]=0;
            for (int i=1; i<=n-1; i++)
            {
                u[i]=read()+1; v[i]=read()+1; l[i]=read();
                add(u[i],v[i],l[i]); add(v[i],u[i],l[i]);
            }
            ans=1e9;
            for (int i=1; i<=n-1; i++)
            {
                memset(d1,0,sizeof(d1));
                memset(d2,0,sizeof(d2));
                memset(up,0,sizeof(up));
                a[0]=u[i]; a[1]=v[i]; 
                dfs1(a[0],0,1);  dfs2(a[0],0,1);
                dfs1(a[1],0,0); dfs2(a[1],0,0);
                d=0; ans1=ans2=1e9;
                for (int j=1; j<=n; j++)
                    d=max(d,d1[j]+d2[j]);
                for (int j=1; j<=n; j++)
                    if (belong[j]==0) ans1=min(ans1,max(up[j],d1[j]));
                    else ans2=min(ans2,max(up[j],d1[j]));
                ans=min(ans,max(d,ans1+ans2+l[i]));
            }
            printf("Case %d: %d
    ",cas,ans);
        }
        return 0;    
    }
    
  • 相关阅读:
    关于技术的学习及批判 人工智能
    爱迪生如何看待手机程序员怎么用移动互联网 人工智能
    量子学习及思考4群体意识 人工智能
    程序员的出路 人工智能
    函数式编程学习之路(14) 人工智能
    量子学习及思考1开篇 人工智能
    函数式编程学习之路(16)图灵完备 人工智能
    开机启动
    动态连接库
    静态常量的问题
  • 原文地址:https://www.cnblogs.com/AGFghy/p/9810439.html
Copyright © 2011-2022 走看看