DFS序學習筆記

2022-07-21 05:12:16 字數 1886 閱讀 7143

1.定義及理解:

dfs序是深度優先遍歷一顆樹的時候產生的時間戳序列,可以將樹形結構有序地轉化為線性結構,從而將樹上問題轉化為線性問題

這時,我們就可以用許多優秀的資料結構,比如維護區間的線段樹、樹狀陣列等方便地處理樹上問題啦!

2.重要的性質

(1)設in[x]表示第一次dfs到x節點的時間戳,out[x]表示從x節點退出的時候的時間戳,num[time]表示time的時間戳所對應的

樹上節點是哪乙個。其中,num陣列是我們新得到的dfs序列,是一段線性節點序。

顯然,一顆以x節點為根的子樹在dfs序中必然佔據一段連續的區間[in[x],out[x]],而這段區間內的所有節點是這顆子樹的所有子節點。

code:

void dfs(int u,int fa)

out[u]=++cnt;//記錄離開x的時間戳

dfs[cnt]=u;//更新dfs序

}(2)問題一:單點修改,子樹和查詢:

求出整棵樹的dfs序,直接單點修改節點x對應在dfs序上的值,然後子樹和也就是求區間和,考慮用樹狀陣列或線段樹維護即可!

問題二:樹鏈修改,單點查詢:

修改(u,v)節點間的值,比如全部加上a

那麼我們考慮對四條鏈進行操作!

考慮u--->root,v--->root,lca(u,v)--->root,fa(lca(uv))--->root!

我們將前兩條路徑上的所有點加a,後兩條路徑的所有點減去a

可以用樹狀陣列維護這個dfs序,序列上依次對應每個dfs序上對應節點的權值!

然後修改?這個樹狀陣列其實維護的是dfs序的權值字首和!

get_sum(x) 表示1-x的差分字首和

add(l[u],a),add(l[v],a),add(lca(u,v),-a),add(fa(lca(u,v)),-a);

val(x)=get_sum(r[x])-get_sum(l[x]-1);

問題三:子樹整體修改,查詢單點到根節點的權值和,以及單點的權值

比如我們對於以x節點為根的子樹整體加a

我們對於所有節點,維護兩個值

乙個是tag,另乙個是節點的自身權值;

我們提供兩種操作:

1)直接進行單點修改

2)將以x為根的子樹整體加a

操作1,直接單點修改即可 操作2,對於所有點,tag+=a,然後節點自身的權值,增加乙個-(dep[x]-1)*a;這個是為了抵消不在這個以x為根

的子樹內的節點的貢獻!詢問節點y到根的權值和的時候,我們返回:tag*dep[y]+val[y];

然後操作即可!

例題:poj3321

洛谷:p3178 樹上操作

dfs學習筆記整理

dfs題型 1.連通塊 就是標記畫圖,算出每個小模組個數 2.尋找到達終點的途徑數 理解dfs其實會無數次到達終點後,每次到達就ans 就可以算出,但是注意回溯時vis x y 要清0.例如下面這個 include include includeusing namespace std const i...

dfs學習筆記 1

這篇文大概就是自己在學習過程中學到的一些模板和注意事項吧,emmm在此先膜拜各路大佬orz 先貼核心 void dfs 引數用來表示狀態 if 越界或者是不合法狀態 return if 特殊狀態 剪枝 return for 擴充套件方式 要注意路徑記錄和節點重判!然後接下來是一些最最最基礎的dfs的...

dfs序 樹狀陣列

the first line contains an integer n n 100,000 which is the number of the forks in the tree.output for every inquiry,output the correspond answer per ...