题目链接: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. C#一维数组

    数组:相同数据类型的元素按照一定的顺序进行排列生成的集合(一组数据)一维数组:int [] array=new int[5];int[] array = new int[] {1,2,3,4,5 }; ...

  2. 【C语言】结构体

    不能定义 struct Node { struct Node a; int b; } 这样的结构,因为为了建立Node 需要 建立一个新的Node a, 可为了建立Node a, 还需要再建立Node ...

  3. LeetCode 217 Contains Duplicate

    Problem: Given an array of integers, find if the array contains any duplicates. Your function should ...

  4. IOS-CoreAnimation

    核心动画 •Core Animation是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍! •使用它需要先添加QuartzCore.framework和引入对应的框架 ...

  5. Android笔记:ListView

    listview属性 android:divider属性,可以指定ListView 分隔线的颜色,#0000 表示将分隔线设为透明色. listview效率的问题 adapter的三个参数int po ...

  6. iOS计算字符串的宽度高度

    OC开发中会遇到根据字符串和字体大小来算计算出字符串所占的宽高->> 封装方法如下: #import <Foundation/Foundation.h> #import < ...

  7. Redis 数据持久化(一)

    Redis的模块化开发设计的还是相当不错的,在Bio.h和Bio.c文件中定义了一个多线程的文件任务处理模块,在添加和处理任务的时候使用互斥锁和条件变量进行的同步,而且本身也支持多线程,这个模块的支持 ...

  8. Git命令之从GitHub上下载开源项目

    1,先在本地创建一个目录,作为本地仓库,如: 2,使用Git init 初始化仓库,git初始化完成后,会生成一个隐藏的git文件如: 3,clone Git项目,如: 4,这个项目就是合Github ...

  9. Mysql控制语句

    14.6.5.1 CASE Syntax 14.6.5.2 IF Syntax 14.6.5.3 ITERATE Syntax 14.6.5.4 LEAVE Syntax 14.6.5.5 LOOP ...

  10. Jpinyin笔记