1. 程式人生 > >樹的DFS

樹的DFS

其他 都是 ++ 一個 多個 lock deep 選擇 for

概念


樹的dfs遍歷就是對於一個樹上每個點 root,它向下的多個分支,選擇一個分支一直走下去,直至走完並回溯到root再走其他分支形成的遍歷。

Code

void dfs(int u,int fa)
{
    vis[u]=1;
    //鄰接表枚舉i的每個相鄰節點
    for(int i=link[u]; i; i=e[i].next)
    {
        int v = e[i].u;
        if(v!=fa)
            dfs(v,u);
    }
}

求樹的深度

每個節點x的深度用deep[x]表示。
代碼只要在dfs向下搜索前deep[e[i].y]=deep[x]+1;


求子樹大小

以x節點為根節點的子樹大小size[x];
在dfs向下搜索之後size[x]+=size[e[i].y];


樹的重心

對於一個節點x,如果把它從樹中刪除,原來的一棵樹可能會分成若幹個不相連的部分,每部分都是一顆子樹。
設 Maxp(x)表示在刪除節點x後分成的子樹中,包含節點最多的那顆子樹的節點數。
對於所有點來說,如果使得Maxp(x)最小的節點x就成為整顆樹的重心。

int pos;//記錄重心的編號
void dfs(int x,int fa)
{
    v[x]=1;
    sz[x]=1;
    int Maxp=0;
    //鄰接表枚舉i的每個相鄰節點
    for(int i=link[x]; i; i=e[i].next)
    {
        int y=e[i].y;
        if(y!=fa)
        {
            dfs(y,x);
            sz[x]+=sz[y];
            Maxp=max(Maxp,sz[y]);
        }
    }
    Maxp=max(Maxp,n-sz[x]);
    if(Maxp<ans)
    {
        ans=Maxp;
        pos=x;
    }
}

樹的DFS序就是在對樹進行DFS的時候,對樹的節點進行重新編號;
DFS序有一個很強的性質: 一顆子樹的所有節點在DFS序內是連續的一段, 利用這個性質我們可以解決很多問題。

void DFS(int u, int fa)
{
    L[u] = ++dfs_clock;
    for(int k = head[u]; ~k; k = E[k].next)
    {
        int v = E[k].to;
        if(v == fa) continue;
        DFS(v, u);
    }
    R[u] = dfs_clock;
}

樹的DFS