靜態仙人掌 模板 tarjan LCA

2021-10-23 15:37:07 字數 3380 閱讀 8318

>description

這是一道靜態仙人掌(block forest data structure)的模板題。

如果您不知道什麼是仙人掌,那麼此處給出無向仙人掌圖的定義:

任意一條邊至多只出現在一條簡單迴路的無向連通圖稱為仙人掌。

給你乙個有 n 個點和 m 條邊的仙人掌圖,和 q 組詢問

每次詢問兩個點 u,v求兩點之間的最短路。

>input

第一行三個正整數 n,m,q,意義如題目描述。

接下來 mmm 行,每行三個正整數 u,v,w,表示 u,v 之間有一條權值為 w 的無向邊。

然後 q 行,每行兩個正整數 u,v,詢問 u 到 v 的最短路。

>output

q 行,每行乙個正整數,對應一次詢問的結果。

>解題思路

(我講的不太好,具體看碼吧==)

樣例的圖是這樣的:

我們要對仙人掌建乙個圓方樹,在每乙個環中間建乙個方點,刪掉環上的路徑,把環上的所有點都連向方點,邊權為其中各個點到dfs序最小的點的最短路

如何找環?(tarjan演算法 )

這裡有兩個陣列:dfn

[i]dfn[i]

dfn[i]

第i點的dfs序,low

[i]low[i]

low[i]

第i點所在的子樹(往下走)可以走到的最小的dfs序

l ow

lowlo

w的作用可以這樣想,如果對於乙個普通的點,low[i]一定為dfn[i],但是對於在環上的乙個點,low[i]就為這個環上dfs序最小的那個點

用樹遞迴下去,如果遇到了環就終止遞迴,判斷環:乙個點i直接相連的乙個點j,如果j的dfs序大於i,並且j的父親不是i,那麼這就是乙個環,並且i是這個環中dfs序最小的,可以進行建環

建出類似下圖這樣的一棵圓方樹:

最後求距離,因為這是一棵樹,所以我們可以用lca求最短路,

有兩種情況:

lca是圓點,直接計算距離就行了

lca是方點,我們要記憶x和y求lca的最後一步x和y,他們的lca是x和y一起往上跳一步,所以x和y一定是兩個圓點,且在同乙個環中,我們的答案要加上x和y之間的最短路(這裡預處理sum)

>**

#include 

#include

#include

#define n

200005

#define int long long

using namespace std;

struct line

a[400005

], aa[

400005];

int n, m, q, t, h[n]

, tt, hh[n]

, dfn[n]

, low[n]

, w, fa[n]

, k[n]

, cnt;

int sum[n]

, dep[n]

, lg[n]

, f[n]

[50], dis[n]

,x,y

;int read()

return l;

}void

write

(int l

)void

add(

int u, int v, int l

); h[u]

= t;

a[++t]

=(line)

; h[v]

= t;

}//建原圖

void

addd

(int u, int v, int l

); hh[u]

= tt;

aa[++tt]

=(line)

; hh[v]

= tt;

}//建圓方圖

void

build

(int u, int v, int l)

//建方點

sum[cnt]

= sum[u]

; x = v;

while

(x != fa[u])}

void

tarjan

(int now)

//tarjan找環

else low[now]

=min

(low[now]

, dfn[a[i]

.to]);

//環的情況,同樣更新low

if(low[a[i]

.to]

> dfn[now]

)addd

(now, a[i]

.to, a[i]

.c);

//圓方樹加入正常的邊

}for

(int i = h[now]

; i; i = a[i]

.next)

if(dfn[a[i]

.to]

> dfn[now]

&& now != fa[a[i]

.to]

)//找環

build

(now, a[i]

.to, a[i]

.c);

}void

dfs(

int now, int fath)}

int lca

(int x, int y

)//求lca

signed main()

tarjan(1

);memset

(dis,

0x7f

,sizeof

(dis));

dis[1]

=0;for

(int i =

1; i <= n; i++

) lg[i]

= lg[i -1]

+(1<< lg[i -1]

== i)

;//log預處理

dfs(1,

0);

int x, y, z, ans =0;

for(int i =

1; i <= q; i++

)write

(ans)

;putchar(10

);}return0;

}

清華集訓2015 靜態仙人掌 仙人掌剖分

毒瘤仙人掌,明明放到樹上一道板題的非要構造到仙人掌上來出題orz orz orz orz orz 在oi的上古時代,流傳著這樣乙個故事 有一天,小w到森林裡遊玩,回來之後跟小v說,我發現好多棵會動的樹耶!小v說,這有什麼好稀奇的,我用手指頭就能維護每棵樹的形態。於是又過了幾天小w到沙漠裡遊玩,回來之...

動態仙人掌(dinosaur

分析 這道題在考場看到我是完全的蒙蔽的,驚人的妄想著能否用資料離散化後的dp來騙分。我果然很菜。好吧,對於我這種菜雞來說,正解似乎有些難想,讓我們考慮從最基本的情況開始考慮。先將所有仙人掌按p為第一關鍵字排序,從左向右掃。這裡我們考慮乙個貪心策略,如果仙人掌兩兩之間距離足夠遠,則仙人掌之間跳躍的最小...

題解 仙人掌計數

題目傳送門 給出 q 個查詢,每次查詢 n 個點的無根有標號仙人掌有多少個。q le 5 times 10 4,n 131072 因為這道題太難碼了,所以先把題解寫了再寫 好奇怪啊 終於碼出來了,果然還是 text 好用 霧 為了方便,我們下面的答案其實求的是有根有標號的答案,最後除以 n 就好了。...