作用:在有向圖中,當詢問從起點到終點的路徑必須經過的點,即去掉這個點以及周圍的邊,就不能從起點到達終點的點(類似於無向圖中的割點)。這時,可與通過建立支配樹來解決問題。
結構:支配樹理所當然是乙個樹狀結構。圖的起點作為根節點,每乙個節點到達根節點的路徑都是必經點。如果能建立這樣的樹狀結構,那麼基本可以通過搜尋求得關於必經點的所有資訊。
在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。要解決的問題就是從眾多矩形中選出最多的矩形,使其可以按要求排成一列,若有多解,矩形編號的字典序要盡可能小。分析 按照書上的分析很簡單易懂,也容易...