樹的DFS
阿新 • • 發佈:2018-05-30
其他 都是 ++ 一個 多個 lock deep 選擇 for
每個節點x的深度用deep[x]表示。
求子樹大小
樹的重心
概念
樹的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);
}
}
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];
在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;
}
}
設 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