POJ 1655 Balancing Act(求树的重心)

题目大意:

就是要求树的重心,重心的定义就是删除这个点使得森林尽量平衡。

也可以让分治子树的时候使得每颗子树的数量在nlogn以内。

思路分析:

son [x] 表示x的子树的数量  不包括自己。

balance 表示最大的森林的节点数。

最后我们要让最大的balance 最小。

balance = max (balance ,n - 1 - son[x]  , son[j] +1)..

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define maxn 20005
#define inf 0x3f3f3f3f
using namespace std;

int tot;
int to[maxn<<1];
int next[maxn<<1];
int head[maxn];
int son[maxn];
int n;
void init()
{
    tot=0;
    memset(head,0,sizeof head);
}
void addedge(int u,int v)
{
    tot++;
    next[tot]=head[u];
    to[tot]=v;
    head[u]=tot;
}
bool vis[maxn];
int ans,ansize;
void dfs(int now)//求树的重心
{
    son[now]=0;
    int balance=0;
    for(int p = head[now] ; p ;p = next[p])
    {
        int v = to[p];
        if(vis[v])continue;
        vis[v]=true;
        dfs(v);
        son[now]+=son[v]+1;
        balance=max(balance,son[v]+1);
    }
    balance=max(balance,n-1-son[now]);
    if(balance<ansize || balance==ansize && now<ans)
    {
        ans=now,ansize=balance;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d",&n);
        for(int i=2;i<=n;i++)
        {
            int s,e;
            scanf("%d%d",&s,&e);
            addedge(s,e);
            addedge(e,s);
        }
        memset(vis,false,sizeof vis);
        ansize=inf;
        vis[1]=true;
        dfs(1);
        printf("%d %d\n",ans,ansize);
    }
    return 0;
}
时间: 2024-10-11 06:42:24

POJ 1655 Balancing Act(求树的重心)的相关文章

poj 1655 Balancing Act 求树的重心【树形dp】

poj 1655 Balancing Act 题意:求树的重心且编号数最小 一棵树的重心是指一个结点u,去掉它后剩下的子树结点数最少. (图片来源: PatrickZhou 感谢博主) 看上面的图就好明白了,不仅要考虑当前结点子树的大小,也要"向上"考虑树的大小. 那么其它就dfs完成就行了,son[] 存以前结点为根的结点个数. 这是用邻接表写: 1 #include<iostream> 2 #include<cstdio> 3 #include<cst

POJ 1655 Balancing Act(求树的重心--树形DP)

题意:求树的重心的编号以及重心删除后得到的最大子树的节点个数size,如果size相同就选取编号最小的. 思路:随便选一个点把无根图转化成有根图,dfs一遍即可dp出答案 //1348K 125MS C++ 1127B #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<vector> using namespace std; int

poj 1655 Balancing Act 【树的重心】

知识点:树的重心 定义:以这个点为根,那么所有的子树(不算整个树自身)的大小都不超过整个树大小的一半. 性质: 性质 1 :树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个距离和,他们的距离和一样. 性质 2 :把两棵树通过某一点相连得到一颗新的树,新的树的重心必然在连接原来两棵树重心的路径上. 性质 3 :一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置. 题目:poj 1655 Balancing Act 题意:给出一颗树,求树的重心点以及重心点删除后中的最大子树.

POJ 1655 Balancing Act(树的重心)

Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14062   Accepted: 5937 Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or m

POJ 1655 Balancing Act (树的重心,常规)

题意:求树的重心,若有多个重心,则输出编号较小者,及其子树中节点最多的数量. 思路: 树的重心:指的是一个点v,在删除点v后,其子树的节点数分别为:u1,u2....,设max(v)为其中的最大值,点v的max(v)是所有点里面最小的,称v为树的重心. 如何求任一重心?按树形来看,max(v)可以由其父亲贡献,也可以由其任一孩子贡献.孩子比较好解决,不就是深搜一遍,然后回溯时统计下数量就行了?而父亲的怎么办?可以知道,点v到其父亲这一叉就是n-sum(v)了,sum(v)指的是以v为根的子树的节

POJ 1655 Balancing Act (树的重心)

题意:求树的重心裸题. 拓展:树的重心可以在树分治时避免退化链时的最坏时间复杂度,提高时间效率. #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue&g

POJ 1655 Balancing Act【树的重心】

Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14251   Accepted: 6027 Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or m

poj1655 Balancing Act 求树的重心

http://poj.org/problem?id=1655 Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9072   Accepted: 3765 Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a fo

POJ 1655 Balancing Act 焦点树

标题效果:鉴于一棵树.除去一个点之后,这棵树将成为一些中国联通的块.之后该点通过寻求取消最低形成块的最大数目. 思维:树DP思维.通过为每个子树尺寸的根节点深搜索确定.之后该节点然后除去,,还有剩下的部分.求一下这些块中数目的最大值.就是去掉这个点时的ans.然后更新总的ans. 这个题事实上就是树的重心. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algori