NOIP2018 保衛王國

2022-08-03 02:03:13 字數 1820 閱讀 9645

給定一棵樹,求它的最小點權覆蓋集,其中允許強制某個點選或不選

ddp用lct維護

明確乙個關係式:最小點權覆蓋集=全集-最大點權獨立集

那麼n≤2000的暴力就很簡單了,暴力修改,然後求最大點權獨立集就好了(我在考場上就是這麼寫的)

關於正解,我採用的是動態dp(動態dp的題解點這裡)

根據上面的式子,我們用動態dp維護最大點權獨立集,然後用全集減去就好了

然後我們考慮強制選點的限制

如果強制乙個點選,那麼我們將這個點的點權加上負無窮

如果強制不選,那麼我們將這個點的點權加上正無窮,然後全集加上正無窮就好了

記得每次操作後要還原現場

時間複雜度是$o(mlogn)$

1 #include 2

using

namespace

std;

3 typedef long

long

ll;4

const

int n = 1e5 + 10;5

const ll inf = 1ll << 40

;6 inline int

read()

13while

(isdigit(c))

17return ret *op;18}

19struct

edge e[n << 1

];22

intnum, head[n];

23struct

matrix

28inline ll getans()

31 inline void

build(ll x, ll y)

35 matrix operator *(const matrix &x) const

43};

44struct

lct a[n];

49int

n, m, val[n];

50ll sum;

51string

s;52 inline void add(int

from, int

to)

57void dfs(int now, int

fa)

67 a[now].x.build(a[now].f[0], a[now].f[1

]);68

}69 inline void update(int

now)

74 inline int isnroot(int

now)

77 inline void rotate(int

x) 91

void splay(int

x) 99

update(x);

100}

101void access(int

x) 108

if(y)

112 a[x].ch[1] =y;

113update(x);

114}

115}

116void change(int

x, ll y)

121void solve(int x, int op1, int y, int

op2)

133int

main()

139for (register int i = 1; i < n; ++i)

143 dfs(1, 0

);144

while (m--)

148return0;

149 }

ac code

NOIP2018 保衛王國

題目 強制選點我們可以把那個點權搞成 inf 強制不選我們搞成 inf 之後就真的成為動態 dp 的板子題了 由於不想像板子那樣再寫乙個最大獨立集的方程,之後利用最小點覆蓋 總點權 最大獨立集的做法,而直接寫了乙個最小點覆蓋的方程,所以寫出了很多鍋 矩陣裡存放相同意義變數的位置可能真實值不相等,於是...

NOIP2018 保衛王國(動態DP)

求最小權值點覆蓋。m mm次詢問,每次給出兩個點,分別要求每個點必須選或必須不選,輸出每次的最小權值覆蓋或者無解輸出 1 1 1強制選或者不選可以看做修改權值為 pm infin 那麼就是這道板題了。include using namespace std typedef long long ll t...

NOIP2018 保衛王國 動態DP

給出一棵樹,有m組詢問,每次詢問給出兩個點,規定他們必須選或必須不選。求樹的最小權覆蓋集。此題有倍增 樹形dp的做法,常數非常優秀,但思路比較難想到。顯然最小權覆蓋集 總點權和 最大權獨立集 看到最大權獨立集,我們想到板子題 luogup4719 模板 動態dp.考慮如何處理詢問。由於我們要權值最小...