图的存储方法采用邻接表存储。
一.树与图的深度优先遍历,树的DFS序,深度与重心、
树与图的深度优先遍历
树可以看作时边数N-1的无向图,图就是图,这样可以达到树与图遍历的代码统一。
void DFS(int x) { //O(n+m)
vis[x] = 1;
for(int i = head[x]; i;i = Next[i]) {
int v = var[i];
if(vis) continue;
DFS(v);
}
}
每个点只走一次,每条边只走一次,如果时无向图则正反各访问一次。以此代码为框架可以统计很多树和图的基本信息。
树的DFS序
一般来讲,我们在对树进行深度优先遍历时,对于每个节点,在刚进入递归的时候以及回溯之前各记录一次该点的编号,这样最后生成的长度为2N的序列就时树的DFS序
//树的dfs序列
void dfs(int u) { //把树看做n-1的无向图 O(n+m)
vis[u] = 1; //记录遍历过的节点
dfn[++cnt] = u; //时间戳
for(int i = head[u]; i; i = Next[i]) {
int v = var[i];
if(vis[v]) continue;
dfs(v);
}
dfn[++cnt] = u;
}
//dfn存储的就是 树的dfs序,一般来说,我们在对树进行深度优先遍历的时候,
//对于每一个节点进入的时候记录一个序号,在回溯之前记录一个序号,得到的序列就是dfs序
通过求树的DFS序我可以把子树的统计转化为序列上的区间统计问题。
树的深度
根节点深度为0,子节点深度 = 父节点 + 1。由此可以见在树上对于边(x,y),d[x] = d[y] + 1。我们在深度优先遍历的时候结合自顶向下的递推就可以很好的统计出树上各各节点的深度信息。
```cpp
//树的深度 根深度为0
int d[maxn];
void getDeeps(int x) { // //O(n+m)
vis[x] = 1;
for(int i = head[x]; i; i = Next[i]) {
int v = var[i];
if(vis[v]) continue;
d[v] = d[x] + 1; //从根往下递推 计算深度
getDeeps(v);
}
}
当然也可以使用广搜,层序遍历来求解。
void bfs() {
//O(n+m)
queue<int> q;
memset(vis,0,sizeof(vis));
d[1] = 1; q.push(1);
while(q.size()) {
int x = q.front();
q.pop();
for(int i = head[x]; i;i = Next[i]) {
int y = var[i];
if(d[y])