學習記錄 DAG上的支配樹

2021-09-25 19:04:16 字數 3522 閱讀 7665

作用:在有向圖中,當詢問從起點到終點的路徑必須經過的點,即去掉這個點以及周圍的邊,就不能從起點到達終點的點(類似於無向圖中的割點)。這時,可與通過建立支配樹來解決問題。

結構:支配樹理所當然是乙個樹狀結構。圖的起點作為根節點,每乙個節點到達根節點的路徑都是必經點。如果能建立這樣的樹狀結構,那麼基本可以通過搜尋求得關於必經點的所有資訊。

在dag上的建樹方法:

總的來說就是,點x在支配樹上的父親就是所有能走到它的點在支配樹上的lca(這個感性理解)。

這樣就可以在o(nlog(n))的時間裡求解,而且還是多個點的;

具體講,就是先進行拓撲排序,然後從前往後依次遍歷,沒遍歷到乙個點,需要根據反向邊來尋找那哪幾個邊能到達這個節點,然後求出幾個點的最近公共組先,就是在支配樹上這個節點的父親。所以需要用倍增找最近公共組先的方法來動態維護二維 f【】【】 陣列(倍增j倍之後i的父節點)和一維 d【】陣列(i號節點的深度)。

在普通的有向圖中建立支配樹:

在普通的有向圖中建樹還是有一定難度的,看了一遍一知半解,大概思路懂了但是具體實現想的不太清楚,之後持續更新。

題目是中文,就不說了。

具體方法就是找每乙個點是從起點到幾個點的必經點。輸出數量。裸的dag上的支配樹建立,建樹之後之需要搜尋一遍求子樹大小即可。

ac**:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

// #include

// #include

#define pb push_back

#define _fileout freopen("out.txt","w",stdout)

#define _filein freopen("in.txt","r",stdin)

#define ok(i) printf("ok%d\n",i)

using

namespace std;

// using namespace __gnu_pbds;

typedef

double db;

typedef

long

long ll;

typedef pair<

int,

int>pii;

const

double pi =

acos(-

1.0)

;const ll mod=

1e9+7;

const ll neg=

1e9+6;

const

int maxn=

1e6+10;

const

int inf=

0x3f3f3f3f

;const ll ll_inf=

9223372036854775807

;const

double eps=

1e-9

;int head[maxn]

,nex[maxn]

,e[maxn]

,o;//正向圖

void

add(

int x,

int y)

//加正向邊

int head2[maxn]

,nex2[maxn]

,e2[maxn]

,o2;

//反向圖

void

add2

(int x,

int y//加逆向邊

int n;

vector<

int>v;

queue<

int>q;

int du[maxn]

;// int vis[maxn];

void

getv()

//拓撲排序更新拓撲序列v}}

int head_zp[maxn]

,nex_zp[maxn]

,e_zp[maxn]

,tot;

//支配樹

void

add_zp

(int x,

int y)

//加支配樹的邊

int f[maxn][20

],d[maxn]

;int t;

intlca

(int x,

int y)

//求最近公共祖先

if(x==y)

return x;

for(

int i=t;i>=

0;i--

)return f[x][0

];}int size[maxn]

;void

dfs(

int x)

//搜尋求每個節點的子樹大小

dfs(y)

; size[x]

+=size[y];}

}int

main()

// printf("du[%d]=%d\n",i,du[i]);

if(du[i]==0

) q.

push

(i);

}getv()

;int len=v.

size()

;// for(int i=0;i//

// printf("\n");

for(

int i=

0;i)// printf("%d %d\n",mid,x);

// printf("lca 2,3=%d\n",lca(2,3));

// ok(1);

add_zp

(mid,x)

;// ok(2);

f[x][0

]=mid;

d[x]

=d[mid]+1

;for

(int l=

1;l<=t;l++)}

// for(int i=1;i<=n;i++)

// // }

for(

int i=

0;i)for

(int i=

1;i<=n;i++

)return0;

}

賞心悅目的ac結果:

支配樹(滅絕樹) 學習筆記

在飛機上的時候理解了一下這個演算法,這裡寫一下吧。本來以前一直以為是個 h 2o 演算法 其實也是 結果發現一些證明還是很有意思的。對於乙個給定圖,我們有如下定義 我們稱 u 為 v 的支配點當且僅當在原圖中刪去 u 之後從根節點出發無法抵達 v 我們稱 u 為 v 的半支配點當且僅當 u 存在一條...

支配樹 Dominator Tree 學習筆記

因為是學習筆記所以是邊學邊寫,以防自己到時候忘掉了 w 首先,支配樹是一棵樹 廢話 用來求解必經點問題。即求乙個有向圖中以r為根到達每乙個點的必經點。樹中每乙個點x的父親為idom x 表示x的最近必經點。我們把從r到x必經y稱作 y支配x 顯然支配是具有傳遞性的。所以可以證明idom是唯一的。首先...

DAG上的動態規劃

dag模型 有n個矩形,每個矩形用兩個整數a,b描述,表示長和寬,矩形 a,b 可以巢狀在矩形 c,d 中,當且僅當a小於c,b小於d或b小於c,a小於d。要解決的問題就是從眾多矩形中選出最多的矩形,使其可以按要求排成一列,若有多解,矩形編號的字典序要盡可能小。分析 按照書上的分析很簡單易懂,也容易...