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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树讲解——树的输入,重心,直径相关的知识,希望对你有一定的参考价值。

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;
}

 

 

 

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

技术分享

 

以上是关于树讲解——树的输入,重心,直径的主要内容,如果未能解决你的问题,请参考以下文章

树的直径与树的重心

树的重心及直径

树的直径与重心

树的直径与重心

POJ 3099 Go Go Gorelians

浅谈树的重心