zoukankan      html  css  js  c++  java
  • 图论:求树的重心

    点击查看折叠代码块
    /*
    树的重心也叫树的质心。对于一棵树n个节点的无根树,找到一个点,
    使得把树变成以该点为根的有根树时,最大子树的结点数最小。
    换句话说,删除这个点后最大连通块(一定是树)的结点数最小。
    
    性质:
    1.树中所有点到某个点的距离和中,到重心的距离和是最小的(实际应用中经常用到此性质)。
    2.把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
    3.一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
    4.一棵树最多有两个重心,且相邻。
    
    求树的重心运用动态规划的思想,也就是树上跑DP。
    */
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1000000;
    const int inf=0x3f3f3f3f;
    
    vector<int>G[maxn];
    int n;
    int size[maxn];//size[i]表示以i为根的子树的节点的个数
    int center;//树的重心
    int st=inf;//st表示删除重心后最大子树的节点数
    
    void dfs(int x,int f){
        size[x]=1;
        int ret=0;//临时变量,记录当前点为根时候的最大子树的节点数
        for (int i=0;i<G[x].size();i++){
            int v=G[x][i];
            if(v==f) continue;
            dfs(v,x);
            size[x]+=size[v];
            ret=max(ret,size[v]);
        }
        ret=max(ret,n-size[x]);
        if(ret<st){
            st=ret;
            center=x;
        }
        // 如果有多个重心且要求序号最小的那个
        if(ret<st || (ret==st && x<center)){
            st=ret;
            center=x;
        }
    }
    
    int main(){
        scanf("%d",&n);
        for (int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1,0);
        printf("%d
    ",center);
        return 0;
    }
    
    你将不再是道具,而是成为人如其名的人
  • 相关阅读:
    自己做一个无敌的文件粉碎机
    编程王道,唯“慢”不破
    在Flex4中嵌入字体
    java函数参数默认值
    Adobe Air移动开发本人体会
    安装VS2013,可是电脑C盘没空间了,今天早上整理了下
    SilverFoxServer出炉!!
    C#中Abstract和Virtual
    解决insert语句插入时,需要写列值的问题
    SQL 标量函数-----日期函数 day() 、month()、year()
  • 原文地址:https://www.cnblogs.com/wsl-lld/p/13393602.html
Copyright © 2011-2022 走看看