poj 1655 找树的重心

树形DP 求树的重心,即选择一个结点删去,使得分出的 若干棵树的结点数 的最大值最小

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include<map>
#include<set>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define mod 998244353
#define pi acos(-1)
#define inf 0x7fffffff
#define ll long long
using namespace std;
ll read()
{
    ll 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*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int T,n,ans;
int size[20005],mx[20005];
vector<int>e[20005];
void dp(int x,int fa)
{
    size[x]=1;
    for(int i=0;i<e[x].size();i++)
    {
        int y=e[x][i];
        if(y==fa)continue;
        dp(y,x);
        size[x]+=size[y];
        mx[x]=max(mx[x],size[y]);
    }
    mx[x]=max(mx[x],n-size[x]);
    if(mx[x]<mx[ans])ans=x;
    if(mx[x]==mx[ans]&&x<ans)ans=x;
}
int main()
{
    T=read();
    while(T--)
    {
        n=read();ans=0;
        mx[0]=inf;
        for(int i=1;i<n;i++)
        {
            int u=read(),v=read();
            e[u].push_back(v);
            e[v].push_back(u);
        }
        dp(1,0);
        printf("%d %d\n",ans,mx[ans]);
        for(int i=1;i<=n;i++)e[i].clear();
        memset(size,0,sizeof(size));
        memset(mx,0,sizeof(mx));
    }
    return 0;
}
时间: 2024-10-14 23:06:30

poj 1655 找树的重心的相关文章

poj1655 Balancing Act(找树的重心)

Balancing Act POJ - 1655 题意:给定一棵树,求树的重心的编号以及重心删除后得到的最大子树的节点个数size,如果size相同就选取编号最小的. /* 找树的重心可以用树形dp或者dfs,这里我用的dfs 基本方法就是随便设定一个根节点,然后找出这个节点的子树大小(包括这个节点),然后总点数减去子树的大小就是向父亲节点走去的点数,使这几部分的最大值最小 */ #include<iostream> #include<cstdio> #include<alg

POJ 1655.Balancing Act-树的重心(DFS) 模板(vector存图)

Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17497   Accepted: 7398 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 3107 Godfather (树的重心)

题目地址:POJ 3107 还是裸的树的重心,只不过这个要求将所有的重心都输出.很简单. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include &

POJ 1655 Balancing Act (树状dp入门)

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 more trees. Define the balance of a node to be the size of the largest tree in the forest T created

树的重心 点分治

最近学了下点分治 说道点分治就得先说到树的重心 树的重心的定义是:最大的子树最小的节点. 为什么要找树的重心呢 因为找到树的重心把他变成根以后,最大的子树的大小不超过n/2,否则如果超过n/2将该子树的根作为重心将会更优. 这样可以保证递归的层数不超过logn层,同时保证每个点最多被计算logn次. 那么如何找重心呢 根据定义,我们不妨维护一下两个数组sz[]和mx[]表示以r为根的子树大小和无根树中的最大子树大小,那么mx最小的那个节点就是重心. 有两种写法 一种是 void getroot(

cqyz oj | 树的分治 | 树形DP | 树的重心

Description 给定一棵N个节点的带权树,定义dist(u,v)为u,v两点间的最短路径长度,路径的长度义为路径上所有边的权和.再给定一个K,如果对于不同的两个结点a,b,如果满足dist(a,b)<=K,则称(a,b)为合法点对. 你的任务是求合法点对个数. Input 第一行包含两个个整数N和K,接下来的N-1行,每行包含三个整数:u,v,len,表示树边(u,v)的长度len. Output 一个整数,表示合法点对的数目. Sample Input 1 5 4 1 2 3 1 3

树的重心专题

解题思路:选择一个节点作为根,设dp[i]表示以i为根的树的总节点个数,dp[i]=满足j为其子节点的的d[j]之和再加1(根节点).只需在dfs过程中找到最大的子树节点,并与其上方的节点数做比较,就可以找出树的重心了. 题目大意:对于一棵无根树,找到一个点使得树以该点为根的有根树,最大子树(选择该节点后其子树的最大节点)的节点数最小. https://blog.csdn.net/qq_41289920/article/details/83933631 https://blog.csdn.net

POJ 1655 Balancing Act (树的重心)

题目地址:POJ 1655 树的重心定义为:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡. 树的重心可以用树形DP快速的找出来. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h>

poj 1655 Balancing Act 【树的重心】

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