zoukankan      html  css  js  c++  java
  • 树的中心

    一、简介

      树的中心是指:一个结点,对于每一个点的距离的最大值最小

    二、解决

      1.Dfs1:标记以结点u为树根的子树链的最大值d1[u],次大值d2[u],以及来源的结点编号c1[u],c2[u]

      2.Dfs2:找到链接结点u没有经过u子树的链的最大值fd[u]

        如果这个点是前一个节点选中的最大链中的,则这个结点的fd[u]=max(fd[fa[u]],d2[fa[u]])+edge[i].dis;

        否则fd[u]=max(fd[fa[u]],d1[fa[u]])+edge[i].dis;

      3.最后fd[u]+d1[u]最小的就是答案了

       

    #include<stdio.h>
    #include<stdlib.h>
    #define FORa(i,s,e) for(int i=s;i<=e;i++)
    #define FORs(i,s,e) for(int i=s;i>=e;i--)
    
    using namespace std;
    const int N=1000,INF=2147483647;
    int n,num_edge,ans=INF,pos,head[N+1],d1[N+1],d2[N+1],c1[N+1],c2[N+1],fd[N+1];
    /*d1[u]表示以u为子树的链的最大值,d2[u]表示以u为子树的链的次大值, 
    c1[u]表示以u为子树的链的最大值的子树结点编号,c2[u]表示以u为子树的链的次大值的子树结点编号
    fd[u]表示的是结点u以上的不经过u子树的链的最大值 
    */ 
    struct Edge{
        int next,to,dis;
    }edge[2*N];
    inline void Add_edge(int from,int to,int dis)
    {
        edge[++num_edge]=(Edge){head[from],to,dis},head[from]=num_edge;
    }
    inline int max(int fa,int fb){return fa>fb?fa:fb;}
    
    inline int Dfs1(int u,int fa,int dis)
    {
        for(int i=head[u];i;i=edge[i].next)
        {
            if(edge[i].to!=fa) 
            {
                Dfs1(edge[i].to,u,dis+edge[i].to);
                if(d1[edge[i].to]+edge[i].dis>d1[u])
                    d2[u]=d1[u],d1[u]=d1[edge[i].to]+edge[i].dis,c2[u]=c1[u],c1[u]=edge[i].to;
                else if(d1[edge[i].to]+edge[i].dis>d2[u])
                    d2[u]=d1[edge[i].to]+edge[i].dis,c2[u]=edge[i].to;
            }
        }
        //Dfs1找到d1,d2,c1,c2; 
    }
    inline int Dfs2(int u,int fa)
    {
        for(int i=head[u];i;i=edge[i].next)
        {
            if(edge[i].to!=fa)
            {
                if(c1[fa]!=edge[i].to) fd[edge[i].to]=max(d1[u],fd[u])+edge[i].dis;//u的最大值中不包含最大链 
                else fd[edge[i].to]=max(d2[u],fd[u])+edge[i].dis;//u的最大值中包含最大链,则用次大链代替 
                Dfs2(edge[i].to,u);
            }
        }
    }
    int main()
    {
        int from,to,dis;
        scanf("%d",&n);
        FORa(i,2,n)
        {
            scanf("%d%d%d",&from,&to,&dis);
            Add_edge(from,to,dis),Add_edge(to,from,dis);
        }
        Dfs1(1,0,0);
        Dfs2(1,0);
        FORa(i,1,n) if(d1[i]+fd[i]<ans) ans=d1[i]+fd[i],pos=i;
        printf("%d %d",pos,ans);
        return 0;
    }
    /*8
    1 2 4
    1 3 2
    2 5 1
    2 6 4
    3 4 9
    5 7 10
    3 8 10
    */

  • 相关阅读:
    OCP-1Z0-053-V12.02-622题
    OCP-1Z0-053-V12.02-501题
    Flex实现查询和重置
    闪回事务处理回退
    闪回数据归档测试
    闪回数据归档
    OCP-1Z0-053-V12.02-166题
    VC-摄像头控制SDK源码
    MFC 的 Picture Control 加载 BMP/PNG 图片的方法
    OCP-1Z0-051-V9.02-25题
  • 原文地址:https://www.cnblogs.com/SeanOcean/p/11311710.html
Copyright © 2011-2022 走看看