版权声明:_ https://blog.csdn.net/lunch__/article/details/84728971
题意
- 给你一个树,每次强制选点或者强制不选,询问最小权覆盖
这个东西就是个动态 模板题
但是我模板打的不熟练调模板调了好久…
不会的话看这篇博客
强制选点通过把权值改为正无穷负无穷来实现
针对这题转移矩阵是这个样子的
注意实现细节与 的取值
Codes
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const ll Inf = 1e17, INF = 1e18;
struct Martix {
ll a[2][2];
Martix() {a[0][0] = a[0][1] = a[1][0] = a[1][1] = INF;}
Martix operator * (const Martix &T) const {
Martix res;
for (int i = 0; i < 2; ++ i)
for (int j = 0; j < 2; ++ j)
for (int k = 0; k < 2; ++ k)
res.a[i][j] = min(res.a[i][j], a[i][k] + T.a[k][j]);
return res;
}
}g[N];
int to[N << 1], nxt[N << 1], head[N], e;
int st[N], ed[N], rel[N], top[N], cnt;
int size[N], fa[N], heavy[N];
int n, m, a[N];
ll f[N][2];
void P(Martix x) {
cout << x.a[0][0] << ' ' << x.a[0][1] << endl << x.a[1][0] << ' ' << x.a[1][1] << endl;
}
inline int read() {
int _ = 0, __ = getchar(), ___ = 1;
for (; !isdigit(__); __ = getchar()) if (__ == '-') ___ = -1;
for (; isdigit(__); __ = getchar()) _ = (_ << 3) + (_ << 1) + (__ ^ 48);
return _ * ___;
}
void add(int x, int y) {
to[++ e] = y; nxt[e] = head[x]; head[x] = e;
}
void dfs1(int x) {
size[x] = 1, f[x][1] = a[x];
for (int i = head[x]; i; i = nxt[i]) if (!size[to[i]]) {
fa[to[i]] = x, dfs1(to[i]);
//注意转移和最大权独立集不一样
f[x][0] += f[to[i]][1];
f[x][1] += min(f[to[i]][0], f[to[i]][1]);
size[x] += size[to[i]];
if (size[to[i]] > size[heavy[x]])
heavy[x] = to[i];
}
ll s0 = f[x][0] - f[heavy[x]][1], s1 = f[x][1] - min(f[heavy[x]][1], f[heavy[x]][0]);
g[x].a[1][0] = s0, g[x].a[0][1] = g[x].a[1][1] = s1;
//转移不一样构造的转移矩阵也不一样
}
void dfs2(int x, int ancestor) {
rel[ed[top[x] = ancestor] = st[x] = ++ cnt] = x;
if (heavy[x]) dfs2(heavy[x], ancestor);
for (int i = head[x]; i; i = nxt[i])
if (!top[to[i]]) dfs2(to[i], to[i]);
}
struct Segment_Tree {
#define mid ((l + r) >> 1)
#define ls (bh << 1)
#define rs (ls | 1)
#define lson ls, l, mid
#define rson rs, mid + 1, r
Martix S[N << 2];
void pushup(int bh) {
S[bh] = S[rs] * S[ls];
}
void build(int bh, int l, int r) {
if (l == r) S[bh] = g[rel[l]];
else build(lson), build(rson), pushup(bh);
}
void update(int bh, int l, int r, int x) {
if (l == r) S[bh] = g[rel[l]];
else {
if (x <= mid) update(lson, x);
else update(rson, x);
pushup(bh);
}在这里插入代码片
}
Martix query(int bh, int l, int r, int x, int y) {
if (x <= l && r <= y) return S[bh];
if (y <= mid) return query(lson, x, y);
if (x > mid) return query(rson, x, y);
return query(rson, x, y) * query(lson, x, y);
}
}T;
void modify(int x, ll y) {
Martix now, lst;
for(; x; x = fa[top[x]]) {
ll del0, del1;
if (y) del1 = y, del0 = y = 0;
else {
del0 = now.a[1][1] - lst.a[1][1];
del1 = min(now.a[1][0], now.a[1][1]) - min(lst.a[1][0], lst.a[1][1]);
}
lst = T.query(1, 1, n, st[top[x]], ed[top[x]]);
g[x].a[1][0] += del0, g[x].a[0][1] += del1, g[x].a[1][1] += del1;
T.update(1, 1, n, st[x]);
//一定注意先更新再查= =我卡在这卡了好久
now = T.query(1, 1, n, st[top[x]], ed[top[x]]);
}
}
int main() {
#ifdef ylsakioi
freopen("5024.in", "r", stdin);
freopen("5024.out", "w", stdout);
#endif
ll A, B, X, Y, ans = 0; char S[N];
n = read(), m = read(), scanf("%s", S);
for (int i = 1; i <= n; ++ i)
a[i] = read();
for (int i = 1; i < n; ++ i) {
X = read(), Y = read();
add(X, Y), add(Y, X);
}
dfs1(1), dfs2(1, 1), T.build(1, 1, n);
//这里一般不会出问题,要挂了肯定上面写错了
for (int i = 1; i <= m; ans = 0, ++ i) {
A = read(), X = read(), B = read(), Y = read();
if (X) X = -Inf, ans -= X; else X = Inf;
if (Y) Y = -Inf, ans -= Y; else Y = Inf;
modify(A, X), modify(B, Y);
Martix res = T.query(1, 1, n, st[1], ed[1]);
modify(A, -X), modify(B, -Y);
ans += min(res.a[1][0], res.a[1][1]);
printf("%lld\n", ans > Inf ? -1 : ans);
}
return 0;
}