1. 程式人生 > >樹講解(2)——樹的輸入,重心,直徑

樹講解(2)——樹的輸入,重心,直徑

str 樹的直徑 names n) ostream push main define span

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

就算慢又怎樣,一步一個腳印,回頭看時,還是有別樣的風采!

技術分享

樹講解(2)——樹的輸入,重心,直徑