dfs序:是指將一棵樹被dfs時所經過的節點順序(不繞回原點)。
尤拉序:就是從根結點出發,按dfs的順序在繞回原點所經過所有點的順序。
通過dfs序判斷v節點的時間區間是否在u節點的時間區間內。
通過尤拉序求u和v的最近公共祖先。
dfs序:a-b-d-e-g-c-f-h
尤拉序:a-b-d-d-e-g-g-e-b-c-f-h-h-f-c-a
時間戳我們有兩個標記,第乙個是第一次訪問的時候記錄一下,然後是在最後一次訪問時再標記一下。
時間戳的性質:我們可以直接通過時間戳來判斷乙個節點是否是另乙個節點的子節點。時間戳之後,那麼樹的每個節點就具有了區間的性質。
dfs序核心**
const int maxn = 1e5+5;
vectorg[maxn]; //存放節點
int s[maxn], e[maxn];//s[maxn]存放「入時間戳」,e[maxn]存放「出時間戳」;
int n,id,len;
int dfsxu[20000];//存放dfs序
void dfs(int u, int fa)
e[u] = id;
}
dfs序完整**
#include using namespace std;
const int maxn = 1e5+5;
vectorg[maxn]; //存放節點
int s[maxn], e[maxn];//s[maxn]存放「入時間戳」,e[maxn]存放「出時間戳」;
int n,id,len;
int dfsxu[20000];//存放dfs序
void dfs(int u, int fa)
e[u] = id;
}int main()
id = 0;
dfs(1, -1);
cout<
for(int i=1;s[i]!=0;i++)
e[u] = id;
}int main()
id = 0;
dfs(1, -1);
for(int i = 1; i <= q; ++i)
else
} return 0;
}
核心**:
vectorg[40010]; //存放節點
int oulaxu[80020]; //存放尤拉序在,在尤拉序中第一次出現為「入時間戳」,第二次出現為「出時間戳」。
int len;
void dfs(int u,int fa)
}void rmq_init()
for(int j = 1; (1<> n >> q;
for(int i = 1; i < n; ++i)
cnt = 0;
dfs(1, -1, 1);
rmq_init();
for(int i = 1; i <= q; ++i)
return 0;
}
DFS序與尤拉序的區別
dfs序 是指將一棵樹被dfs時所經過的節點順序 不繞回原點 尤拉序 就是從根結點出發,按dfs的順序在繞回原點所經過所有點的順序。通過dfs序判斷v節點的時間區間是否在u節點的時間區間內。通過尤拉序求u和v的最近公共祖先。dfs序 a b d e g c f h 尤拉序 a b d d e g g...
雙重祖先(DFS序的應用)
dfs序 可以讓我們在 線性的陣列內 處理樹上的子樹等問題 所以我們只需要給第乙個樹 建立dfs序,然後用線段樹 或者樹狀陣列 維護一下就好了 第一棵樹的dfs序 第二顆樹 直接查詢 節點 3 的祖先 裡 哪些 也是第一棵樹的祖先 用線段樹 1.對兩個 1 節點區間 內所有數 1 2.對兩個 2 節...
選點 巧妙的dfs序dp
傳送門 注意一下這兩句話 如果選了根節點的話,在這棵子樹內選的其他的點都要比根節點的值大 如果在左子樹選了乙個點,在右子樹中選的其他點要比它小。根節點比子節點都要小 右子樹比左子樹都要大 所以可以跑dfs dfsdf s序維護最長上公升子串行來寫 include using namespace st...