首页 > 其他分享 >求树的重心

求树的重心

时间:2023-05-31 19:03:23浏览次数:39  
标签:const 重心 int 最小值 求树 include


题目:http://poj.org/problem?id=1655


题意:给定一棵树,求树的重心的编号以及重心删除后得到的最大子树的节点个数size,如果size相同就选取编号最小的.


分析:首先要知道什么是树的重心,树的重心定义为:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重

心后,生成的多棵树尽可能平衡.  实际上树的重心在树的点分治中有重要的作用, 可以避免N^2的极端复杂度(从退化链的一端出发),保证

NlogN的复杂度, 利用树型dp可以很好地求树的重心.



#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;
const int N = 20005;
const int INF = 1<<30;

int head[N];
int son[N];
bool vis[N];
int cnt,n;
int ans,size;

struct Edge
{
    int to;
    int next;
};

Edge edge[2*N];

void Init()
{
    cnt = 0;
    size = INF;
    memset(vis,0,sizeof(vis));
    memset(head,-1,sizeof(head));
}

void add(int u,int v)
{
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}

void dfs(int cur)
{
    vis[cur] = 1;
    son[cur] = 0;
    int tmp = 0;
    for(int i=head[cur];~i;i=edge[i].next)
    {
        int u = edge[i].to;
        if(!vis[u])
        {
            dfs(u);
            son[cur] += son[u] + 1;
            tmp = max(tmp,son[u] + 1);
        }
    }
    tmp = max(tmp,n-son[cur]-1);
    if(tmp < size || tmp == size && cur < ans)
    {
        ans = cur;
        size = tmp;
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        Init();
        scanf("%d",&n);
        for(int i=1;i<=n-1;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        dfs(1);
        printf("%d %d\n",ans,size);
    }
    return 0;
}




题目:http://poj.org/problem?id=3107


题意:给定一棵树,求树的所有重心,按照编号从小到大的顺序输出.


分析:本题与上题基本上一样,只是求的量不同,既然我们在找树的重心的时候用的树型dp,而且是求的子树中节点数的最大值,然后求所有最

大值的最小值,那么就有可能存在多个重心,我们每更新到一个最小值的时候就记录其它的最小值也为这个最小值的重心,这样下去就会找到所

有的重心.



#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>

using namespace std;
const int N = 50005;
const int INF = 1<<30;

int head[N];
int son[N];
bool vis[N];
int cnt,n;
int num,size;
int ans[N];

struct Edge
{
    int to;
    int next;
};

Edge edge[2*N];

void Init()
{
    cnt = 0;
    num = 0;
    size = INF;
    memset(vis,0,sizeof(vis));
    memset(head,-1,sizeof(head));
}

void add(int u,int v)
{
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}

void dfs(int cur)
{
    vis[cur] = 1;
    son[cur] = 0;
    int tmp = 0;
    for(int i=head[cur];~i;i=edge[i].next)
    {
        int u = edge[i].to;
        if(!vis[u])
        {
            dfs(u);
            son[cur] += son[u] + 1;
            tmp = max(tmp,son[u] + 1);
        }
    }
    tmp = max(tmp,n-son[cur]-1);
    if(tmp < size)
    {
        num = 1;
        ans[0] = cur;
        size = tmp;
    }
    else if(tmp == size)
    {
        ans[num++] = cur;
    }
}

int main()
{
    while(~scanf("%d",&n))
    {
        Init();
        for(int i=1;i<=n-1;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        dfs(1);
        sort(ans,ans+num);
        for(int i=0;i<num;i++)
            printf("%d ",ans[i]);
        puts("");
    }
    return 0;
}





标签:const,重心,int,最小值,求树,include
From: https://blog.51cto.com/u_16146153/6388994

相关文章

  • HDU3662(求三维凸包表面的多边形个数,表面三角形个数,体积,表面积,凸包重心,凸包中点到面
    题目:3DConvexHull题意:给定空间中的n个点,求这n个点形成的凸包的表面的多边形个数。增量法求解:首先任选4个点形成的一个四面体,然后每次新加一个点,分两种情况:1>在凸包内,则可以跳过2>在凸包外,找到从这个点可以"看见"的面S(看不看得见可以用法向量,看点是否在面外侧),删除这些......
  • 9.重心与吊装
    重心与起重作业的关系重心就是物体分割成许多微小体积的重力的合力中心。重心与起重作业的安全关系重大,在起重安全施工规范中明确地规定:吊钩作用线与重物的重心必须在同一条垂直线上。物体的重心位置是进行起重施工所必须掌握的重要技术数据之一。重心与起重作业的关......
  • CF1824B2 LuoTianyi and the Floating Islands (Hard Version) - 概率期望 - 树的重心
    题目链接:https://codeforces.com/contest/1824/problem/B2题解:考虑一棵\(n\)个点的树,假如已经选定了\(k\)个特殊点,如何判断某一个点是否为好点?显然将这个点提到根没有影响,那么好点的充要条件是对于所有子树的\(S_u\)值都\(\leqk/2\),这里\(S\)代表\(u\)子树中的特殊......
  • 产品经理-基础-重心-误区
    基础1、视野(扩展)、国内外产品资料2、表达能力(笔记、草稿)3、技术:前端H5.......4、逻辑思维:设计与用户使用是否缺陷5、基础电脑操作重心1、实操2、认识外-->内,重点难点3、流程误区1、盲从、信大厂2、捞针,无目的3、重工具(要注重整体)、RP......
  • 人物速写随笔-重心
    通常重心线是第七节椎骨的垂直线 ......
  • 树的重心
    定义:1.找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心。2.以这个点为根,那么所有的子树(不算整个树自身)的大小都不超过整个树大小的一半。性质:1.树......
  • POJ 1655 Balancing Act 树的重心
    BalancingActTimeLimit: 1000MS MemoryLimit: 65536KTotalSubmissions: 16866 Accepted: 7130DescriptionConsideratreeTwithN(1<=N<=20,000)nodesnu......
  • 【题解】P5666 [CSP-S2019] 树的重心
    感觉对重心的理解更直观了一点。题意求一棵树上删去每一条边后两侧子树重心的编号和。\(n\leq3\times10^5\)思路神奇的清真数论。首先这里有一步很妙的操作:把整......
  • Codeforces 1654 G Snowy Mountain 题解 (重心分治)
    题目链接假设现在起点已经确定,我们观察从这个起点开始能走的最长路径长什么样。把这条最长路径中所有的非平地路径拿出来,它们肯定连成一线,因为不允许上坡;而一条路径重复走......
  • 接手旺铺转让要立足的重心,助你成功接手
     同样是接手一个旺铺转让进行开店,为什么别人的旺铺可以迅速发展起来,自己接手的旺铺却始终发展不起来呢?关键在于自己接手时有没有立足一些重心,今天铺先生为大家讲述接手旺......