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;    
    }
    
  • 相关阅读:
    将h.264视频流封装成flv格式文件(一.flv格式)(转载)<a href="http://blog.csdn.net/yeyumin89/article/details/7932368"></a>
    01背包,求最大值
    JNI vc6.0 dll
    jni java c++ 参数传递问题解决
    (转载)将h.264视频流封装成flv格式文件(二.开始动手)http://blog.csdn.net/yeyumin89/article/details/7932431
    达到最高效益的调度
    按照RFC3984协议实现H264视频流媒体
    语音识别 转载 待测试
    活动选择问题 动态规划算法(最大子集合或最大收益)
    整齐打印
  • 原文地址:https://www.cnblogs.com/AGFghy/p/9810439.html
Copyright © 2011-2022 走看看