虛樹 P2495 SDOI2011 消耗戰

2021-10-04 02:48:56 字數 1949 閱讀 8115

好久沒有學習新的知識了。

今天我學習了一下虛樹。

虛樹就是乙個不存在的樹。用來簡化問題。它只包括一些關鍵點和他的lca

我們來看看上面這一道題

給出一棵樹,含有邊權。

每次詢問給出k個點,然後詢問每個點與根斷開的最小代價。

因為資料的關係肯定沒法直接dp過去的。

首先我們可以發現可以與根到其他點的路徑沒有關係,所以只要儲存詢問點到根以及lca的資訊就可以了。那麼這就是虛樹了。

關於虛樹的構造,網上有很多部落格寫得不錯,我就不講了。

下面講怎麼虛樹上處理dp

包括兩種情況:

1.斷開自己與父親,代價為從根到該節點的最小值。

2.不考慮該點,子樹內的所有詢問點都斷開的代價。

具體看**吧。

#include

"bits/stdc++.h"

using

namespace std;

inline

intread()

#define sz(x) ((int)x.size())

#define ll long long

const

int maxn =

250000+10

;struct edge ed[maxn <<1]

;int head[maxn <<1]

, cnt;

void

add_e

(int u,

int v,

int w)

; head[u]

= cnt;

}int top[maxn]

, id[maxn]

, f[maxn]

, dep[maxn]

, sz[maxn]

, son[maxn]

, rk[maxn]

;ll mn[maxn]

;void

dfs1

(int u,

int fa,

int d)

}void

dfs2

(int u,

int t)

}int

lca(

int x,

int y)

if(dep[x]

> dep[y]

)return y;

return x;

}bool

cmp(

intconst

&a,int

const

&b)int n, m, k, a[maxn]

, s[maxn]

, st;

vector<

int> g[maxn]

;void

build

(int x)

int lca =

lca(x, s[st]);

if(lca == s[st]

)return

;while

(st >

1&& id[s[st -1]

]>= id[lca])if

(lca != s[st]

) g[lca]

.push_back

(s[st]

), s[st]

= lca;

s[++st]

= x;

}ll solve

(int u)

g[u]

.clear()

;return

min(sum, mn[u]);

}int

main()

dfs1(1

,0,1

);cnt =0;

dfs2(1

,1);

m =read()

;while

(m--

)return0;

}

P2495 SDOI2011 消耗戰 虛樹

這是我做的第一道虛樹題啊,趕腳不錯.其實虛樹也沒什麼奇怪的,就是每棵樹給你一些點,讓你多次查詢,但是我不想每次都o n 所以我們每次針對給的點建一棵虛樹,只包含這些點和lca,然後在這棵虛樹上進行樹形dp,維護每個點的最小連邊權值,這樣的複雜度就會降低不少.這裡我寫了兩種寫法 其實都是抄的 一種是正...

P2495 SDOI2011 消耗戰 虛樹

題意 一棵樹上給定點集,求到根的最小割。每次詢問只和給定的點集以及它們的lca有關係,那麼把這些點拿出來建立一棵樹。再進行樹dp。具體操作把所有詢問點按照dfn排序,再用乙個棧進行維護建樹。彈棧的時候並不是每個點都和棧中第二個元素連邊,有可能最後乙個彈棧點和新的lca連邊。dp轉移時需要查詢樹鏈的最...

SDOI2011 消耗戰 虛樹

有m次詢問,又有詢問的總的點數之和是小於等於5e5的,所以,其實就是乙個虛樹的模板了,直接用棧維護乙個虛樹即可。期間寫的時候出現了一點問題 初始化的時候,不只是要初始那些輸入的k個結點,還有k個結點的lca的衍生結點也是需要初始化的,所以初始化不到位會mle和tle的,這裡不要忘。include i...