給定一棵樹,求它的最小點權覆蓋集,其中允許強制某個點選或不選
ddp用lct維護
明確乙個關係式:最小點權覆蓋集=全集-最大點權獨立集
那麼n≤2000的暴力就很簡單了,暴力修改,然後求最大點權獨立集就好了(我在考場上就是這麼寫的)
關於正解,我採用的是動態dp(動態dp的題解點這裡)
根據上面的式子,我們用動態dp維護最大點權獨立集,然後用全集減去就好了
然後我們考慮強制選點的限制
如果強制乙個點選,那麼我們將這個點的點權加上負無窮
如果強制不選,那麼我們將這個點的點權加上正無窮,然後全集加上正無窮就好了
記得每次操作後要還原現場
時間複雜度是$o(mlogn)$
1 #include 2ac codeusing
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 }
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.考慮如何處理詢問。由於我們要權值最小...