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

求树的重心,所谓树的重心就是:在无根树转换为有根树的过程中,去掉根节点之后,剩下的树的最大结点最小,该点即为重心。

剩下的数的 最大结点dp[i]=max(max(s[j]),n-s[i])  其中的s[i]为以i为根节点的子树的结点总数,j为i的孩子。

//思路和代码都是比较好理解的

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=5e4+;
const int INF=0x3f3f3f3f; struct Edge
{
int v;
int next;
} edge[maxn<<]; int dp[maxn];
int s[maxn];
int head[maxn];
int n,k; void init()
{
k=;
memset(head,-,sizeof(head));
} void addedge(int u,int v)
{
edge[k].v=v;
edge[k].next=head[u];
head[u]=k++; edge[k].v=u;
edge[k].next=head[v];
head[v]=k++;
} void dfs1(int u,int p)
{
s[u]=;
for(int i=head[u]; i!=-; i=edge[i].next)
{
int v=edge[i].v;
if(v==p) continue;
dfs1(v,u);
s[u]+=s[v];
}
} void dfs2(int u,int p)
{
for(int i=head[u]; i!=-; i=edge[i].next)
{
int v=edge[i].v;
if(v==p) continue;
dp[u]=max(dp[u],s[v]);
dfs2(v,u);
}
dp[u]=max(dp[u],n-s[u]);
} int main()
{
while(scanf("%d",&n)==)
{
init();
int a,b;
for(int i=; i<n; i++)
{
scanf("%d%d",&a,&b);
addedge(a,b);
}
memset(dp,,sizeof(dp));
dfs1(,-);
dfs2(,-);
int ans=INF;
for(int i=; i<=n; i++)
if(dp[i]<ans) ans=dp[i];
int flag=;
for(int i=; i<=n; i++)
{
if(dp[i]==ans)
{
if(flag==)
{
printf("%d",i);
flag=;
}
else
printf(" %d",i);
}
}
printf("\n");
}
return ;
}

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

求树的重心,输出重心和结点最少的树的结点数。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=5e4+;
const int INF=0x3f3f3f3f; struct Edge
{
int v;
int next;
} edge[maxn<<]; int dp[maxn];
int s[maxn];
int head[maxn];
int n,k; void init()
{
k=;
memset(head,-,sizeof(head));
} void addedge(int u,int v)
{
edge[k].v=v;
edge[k].next=head[u];
head[u]=k++; edge[k].v=u;
edge[k].next=head[v];
head[v]=k++;
} void dfs1(int u,int p)
{
s[u]=;
for(int i=head[u]; i!=-; i=edge[i].next)
{
int v=edge[i].v;
if(v==p) continue;
dfs1(v,u);
s[u]+=s[v];
}
} void dfs2(int u,int p)
{
for(int i=head[u]; i!=-; i=edge[i].next)
{
int v=edge[i].v;
if(v==p) continue;
dp[u]=max(dp[u],s[v]);
dfs2(v,u);
}
dp[u]=max(dp[u],n-s[u]);
} int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
for(int t=; t<=T; t++)
{
scanf("%d",&n);
init();
int a,b;
for(int i=; i<n; i++)
{
scanf("%d%d",&a,&b);
addedge(a,b);
}
memset(dp,,sizeof(dp));
dfs1(,-);
dfs2(,-);
int ans=INF,k;
for(int i=; i<=n; i++)
if(dp[i]<ans) k=i,ans=dp[i];
printf("%d %d\n",k,ans);
}
return ;
}

poj3107 求树的重心(&& poj1655 同样求树的重心)的更多相关文章

  1. poj 2001:Shortest Prefixes(字典树,经典题,求最短唯一前缀)

    Shortest Prefixes Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 12731   Accepted: 544 ...

  2. Codeforces 390E Inna and Large Sweet Matrix 树状数组改段求段

    题目链接:点击打开链接 题意:给定n*m的二维平面 w个操作 int mp[n][m] = { 0 }; 1.0 (x1,y1) (x2,y2) value for i : x1 to x2 for ...

  3. POJ 2104 K-th Number ( 求取区间 K 大值 || 主席树 || 离线线段树)

    题意 : 给出一个含有 N 个数的序列,然后有 M 次问询,每次问询包含 ( L, R, K ) 要求你给出 L 到 R 这个区间的第 K 大是几 分析 : 求取区间 K 大值是个经典的问题,可以使用 ...

  4. [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树)

    [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树) 题面 给出一棵N个点的树,Q次询问一点编号在区间[l1,r1]内,另一点编号在区间[l2,r2]内的所有点对距离最大值.\ ...

  5. 树链剖分与倍增求LCA

    树链剖分与倍增求\(LCA\) 首先我要吐槽机房的辣基供电情况,我之前写了一上午,马上就要完成的时候突然停电,然后\(GG\)成了送链剖分 其次,我没歧视\(tarjan LCA\) 1.倍增求\(L ...

  6. Java实现二叉搜索树的添加,前序、后序、中序及层序遍历,求树的节点数,求树的最大值、最小值,查找等操作

    什么也不说了,直接上代码. 首先是节点类,大家都懂得 /** * 二叉树的节点类 * * @author HeYufan * * @param <T> */ class Node<T ...

  7. Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)

    Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...

  8. NYOJ 35 表达式求值(逆波兰式求值)

    http://acm.nyist.net/JudgeOnline/problemset.php?typeid=4 NYOJ 35 表达式求值(逆波兰式求值) 逆波兰式式也称后缀表达式. 一般的表达式求 ...

  9. 数论-质数 poj2689,阶乘分解,求阶乘的尾零hdu1124, 求尾零为x的最小阶乘

    /* 要求出[1,R]之间的质数会超时,但是要判断[L,R]之间的数是否是素数却不用筛到R 因为要一个合数n的最大质因子不会超过sqrt(n) 所以只要将[2,sqrt(R)]之间的素数筛出来,再用这 ...

  10. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

随机推荐

  1. 后台session过期,tomcat重启,自动跳转页面js写法

    if (window != top) { //top.location.href = location.href;//因为系统分为普通用户和后台,所以暂时写死 if(top.location.href ...

  2. 【leetcode】Maximum Gap(hard)★

    Given an unsorted array, find the maximum difference between the successive elements in its sorted f ...

  3. LeetCode 409 Longest Palindrome

    Problem: Given a string which consists of lowercase or uppercase letters, find the length of the lon ...

  4. POJ 1830 开关问题 (高斯消元)

    题目链接 题意:中文题,和上篇博客POJ 1222是一类题. 题解:如果有解,解的个数便是2^(自由变元个数),因为每个变元都有两种选择. 代码: #include <iostream> ...

  5. [Android Pro] android 4.4 Android原生权限管理:AppOps

    reference : http://m.blog.csdn.net/blog/langzxz/45308199 reference : http://blog.csdn.net/hyhyl1990/ ...

  6. jvm学习

    一.jps主要用来输出JVM中运行的进程状态信息 jps [options] [hostid] 如果不指定hostid就默认为当前主机或服务器. Jps -ml 二.jstack主要用来查看某个Jav ...

  7. LR性能指标分析

    Memory: ·Available Mbytes 简述:可用物理内存数.如果Available Mbytes的值很小(4 MB或更小),则说明计算机上总的内存可能不足,或某程序没有释放内存. 参考值 ...

  8. JQ JSON数据类型

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. linux查看常用操作

    linux下查看文件夹以及文件的大小: df命令可以显示目前所有文件系统的可用空间及使用情形 df -h Filesystem Size Used Avail Use% Mounted on /dev ...

  10. Dubbo应用与异常记录

    结合项目里使用暴露出的问题,对并发较多的核心业务或者对请求失败等敏感的业务场景不太建议使用Dubbo, 如电商的购买等行为,使用Dubbo就必须阅读源码,熟悉相关机制,或者直接自己造轮子. >& ...