树讲解(2)——树的输入,重心,直径

one.树的输入

1.输入每个节点父亲节点的编号

#include<vector>
#include<stdio.h>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100000
#define maxn 123456
using namespace std;
int n,x,fa[N];
bool vis[N];
vector<int>vec[N];
void dfs(int x)
{
    vis[x]=1;
    for(int i=0;i<vec[x].size();i++)
     dfs(vec[x][i]);

}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        fa[i]=x;
        vec[x].push_back(i);//由x向i连一条有向边
    }
    dfs(1);
}

2.直接输入树上n-1条边,不确定根

#include<vector>
#include<stdio.h>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 10000
#define maxn 123456
using namespace std;
vector<int>vec[N];
int n,x,y,fa[N];
bool vis[N];
void dfs(int x)
{
    vis[x]=1;
    for(int i=0;i<vec[x].size();i++)
    {
        if(vec[x][i]!=fa[x])
        {
            fa[vec[x][i]]=x;
            dfs(vec[x][i]);
         }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        vec[x].push_back(y);
        vec[y].push_back(x);
    }
    dfs(1);
    return 0;
}

two。树的直径

树的直径即为在这棵树上最长的简单路径。

做法:

首先,我们先随便找一个点为各节点对整棵树进行一下dfs,求出离这个点最远的节点t

然后,我们在以t点为根节点对整棵树进行一下dfs,求出这个点最远的节点m

这样我们就称tm是这棵树的直径!

求树的直径的代码

#include<vector>
#include<stdio.h>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 10000
#define maxn 123456
using namespace std;
vector<int>vec[N];
int n,x,y,fa[N],s,t,dis[N];
void dfs(int x)
{
    for(int i=0;i<vec[x].size();i++)
    {
        if(!dis[vec[x][i]])
        {
            dis[vec[x][i]]=dis[x]+1;
            dfs(vec[x][i]);
          }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        vec[x].push_back(y);
        vec[y].push_back(x);
    }
    dis[1]=1;
    dfs(1);
    for(int i=t=1;i<=n;i++)
     if(dis[t]>dis[i])
       t=i;
    memset(dis,0,sizeof(dis));
    dis[t]=1;
    dfs(t);
    for(int i=s=1;i<=n;i++)
      if(dis[s]>dis[i])
       s=i;
    printf("%d",dis[s]-1);
    return 0;
 } 

three。树的重心

找到一个点,若这个点满足他的子树中的最大子节点数最少,那这个点就是树的重心

在树的总点数是偶数的时候,一个树可能有两个重心。

在找树的重心时,随意确定一个根,对整棵树进行一遍dfs,找出每个节点的子节点的个数

一棵树的重心满足他的子节点的个数:2*sizei>=n,但他的子节点2*sizei<=n,那这个点就是树的重心

代码

#include<vector>
#include<stdio.h>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100000
#define maxn 123456
using namespace std;
vector<int>vec[N];
int n,x,y,ans,size[N],fa[N];
void dfs(int x)
{
    size[x]=1;
    for(int i=0;i<vec[x].size();i++)
    {
        if(fa[x]!=vec[x][i])
         {
             fa[vec[x][i]]=x;
            dfs(vec[x][i]);
            size[x]+=size[vec[x][i]];
         }
    }
    if(!ans&&size[x]*2>=n)
      ans=x;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
      scanf("%d%d",&x,&y);
      vec[x].push_back(y);
      vec[y].push_back(x);
    }
    dfs(1);
    printf("%d",ans);
    return 0;
}

就算慢又怎样,一步一个脚印,回头看时,还是有别样的风采!

时间: 2024-10-14 23:20:54

树讲解(2)——树的输入,重心,直径的相关文章

讲解——线段树

   讲解--线段树 O.引例 A.给出n个数,n<=100,和m个询问,每次询问区间[l,r]的和,并输出. 一种回答:这也太简单了,O(n)枚举搜索就行了. 另一种回答:还用得着o(n)枚举,前缀和o(1)就搞定. 那好,我再修改一下题目. B.给出n个数,n<=100,和m个操作,每个操作可能有两种:1.在某个位置加上一个数:2.询问区间[l,r]的和,并输出. 回答:o(n)枚举. 动态修改最起码不能用静态的前缀和做了. 好,我再修改题目: C.给出n个数,n<=1000000,

Trie树讲解

Trie树简介:又称字典树.前缀树.单词查找树或键树,是一种用于快速检索的树形结构,是一种哈希树的变种 用途: 1.字符串检索:实现将一些字符串的有关信息保存到trie树中,查找另外一些字符串是否出现过或者出现的频率 2.前缀匹配:匹配前缀 3.排序:tire树是一颗多叉树,只需先序遍历整棵树,输出相应的字符串便是按字典序排序的结果 4.作为其他数据结构和算法的辅助结构:ac自动机.后缀数组 特点: 1.时间:建树时间复杂度 O(n*len),如果要查找长度为len的字符串是否存在,时间复杂度O

主席树讲解

以下转自http://prominences.weebly.com/1/post/2013/02/1.html 可持久化线段树,也叫作函数式线段树,也就是主席树,(...因为先驱就是fotile主席..Orz...)网上的教程很少啊,有的教程写得特别简单,4行中文,然后就是一篇代码--这里,我将从查找区间第k小值(不带修改)题的可持久化线段树做法中,讲一讲主席树./*只是略懂,若有错误,还请多多包涵!*/可持久化数据结构(Persistent data structure)就是利用函数式编程的思

从B树、B+树、B*树谈到R 树

第一节.B树.B+树.B*树 1.前言: 动态查找树主要有:二叉查找树(Binary Search Tree),平衡二叉查找树(Balanced Binary Search Tree),红黑树(Red-Black Tree ),B-tree/B+-tree/ B*-tree(B~Tree).前三者是典型的二叉查找树结构,其查找的时间复杂度O(log2N)与树的深度相关,那么降低树的深度自然会提高查找效率. 但是咱们有面对这样一个实际问题:就是大规模数据存储中,实现索引查询这样一个实际背景下,树节

B树、Trie树详解

查找(二) 散列表 散列表是普通数组概念的推广.由于对普通数组可以直接寻址,使得能在O(1)时间内访问数组中的任意位置.在散列表中,不是直接把关键字作为数组的下标,而是根据关键字计算出相应的下标. 使用散列的查找算法分为两步.第一步是用散列函数将被查找的键转化为数组的一个索引. 我们需要面对两个或多个键都会散列到相同的索引值的情况.因此,第二步就是一个处理碰撞冲突的过程,由两种经典解决碰撞的方法:拉链法和线性探测法. 散列表是算法在时间和空间上作出权衡的经典例子. 如果没有内存限制,我们可以直接

从B 树、B+ 树、B* 树谈到R 树

从B 树.B+ 树.B* 树谈到R 树 作者:July.weedge.Frankie.编程艺术室出品. 说明:本文从B树开始谈起,然后论述B+树.B*树,最后谈到R 树.其中B树.B+树及B*树部分由weedge完成,R 树部分由Frankie完成,全文最终由July统稿修订完成. 出处:http://blog.csdn.net/v_JULY_v . 第一节.B树.B+树.B*树 1.前言: 动态查找树主要有:二叉查找树(Binary Search Tree),平衡二叉查找树(Balanced

从B 树、B+ 树、B* 树谈到R 树(转)

  作者:July.weedge.Frankie.编程艺术室出品. 说明:本文从B树开始谈起,然后论述B+树.B*树,最后谈到R 树.其中B树.B+树及B*树部分由weedge完成,R 树部分由Frankie完成,全文最终由July统稿修订完成. 出处:http://blog.csdn.net/v_JULY_v . 第一节.B树.B+树.B*树 1.前言: 动态查找树主要有:二叉查找树(Binary Search Tree),平衡二叉查找树(Balanced Binary Search Tree

查找(二)简单清晰的B树、Trie树详解

查找(二) 散列表 散列表是普通数组概念的推广.由于对普通数组可以直接寻址,使得能在O(1)时间内访问数组中的任意位置.在散列表中,不是直接把关键字作为数组的下标,而是根据关键字计算出相应的下标. 使用散列的查找算法分为两步.第一步是用散列函数将被查找的键转化为数组的一个索引. 我们需要面对两个或多个键都会散列到相同的索引值的情况.因此,第二步就是一个处理碰撞冲突的过程,由两种经典解决碰撞的方法:拉链法和线性探测法. 散列表是算法在时间和空间上作出权衡的经典例子. 如果没有内存限制,我们可以直接

【经典数据结构】B树与B+树

本文转载自:http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html 维基百科对B树的定义为“在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据.对其进行排序并允许以O(log n)的时间复杂度运行进行查找.顺序读取.插入和删除的数据结构.B树,概括来说是一个节点可以拥有多于2个子节点的二叉查找树.与自平衡二叉查找树不同,B-树为系统最优化大块数据的读和写操作.B-tree算法减少定位记录时

HDOJ1556 Color the ball 【线段树】+【树状数组】+【标记法】

Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 8272    Accepted Submission(s): 4239 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽"牌