"Solution" Luogu P3267 Scout Guard

Brief description of the title

To give you a tree, placing a guard on a certain point requires a certain price and a certain effective range. Let you cover some specified points and find the minimum cost

answer

Algorithm tags:

$ \ \ \ \ \ \ \ \ \ Tree DP

DP status definition:

$ \ \ \ \ \ \ \ \ \ $ To be honest, this question is not easy to determine.

$ \ \ \ \ \ \ \ \ \ $ So from the beginning, when \ (d = 0 \) , we are looking for the largest independent set of trees, the definition is obvious.

$ \ \ \ \ \ \ \ \ \ $ \ (d \ neq 0 \) We can copy the original definition and expand it.


$ \ \ \ \ \ \ \ \ \ $ \ (f_ (i, j) \) means that the subtree with \ (i \) as the root node has been completely covered so that it can also be covered up \ (j \) Layer minimum cost

$ \ \ \ \ \ \ \ \ \ $ \ (g_ (i, j) = \) means that the subtree with \ (i \) as the root node also has the minimum cost of the uncovered \ (j \) layer


$ \ \ \ \ \ \ \ \ \ $ It should be noted that \ (j \) is essentially directional and can be analogized to the concept of vector.

$ \ \ \ \ \ \ \ \ \ $ The boundary conditions are obvious. \ (F_ {i, 0} = val_ {i} \) At this time, the current node needs to be overwritten.

$ \ \ \ \ \ \ \ \ \ $ Other circumstances:

\[\begin{cases} f_{i,j}=val_{i},j\in [1,d] \\ \displaystyle f_{i,j}=\infty,j=d+1 \end{cases} \]

$ \ \ \ \ \ \ \ \ \ $ State transfer equations are more imaginable, so I wo n’t repeat them here.

#include <cstdio>
#include <algorithm>
#include <queue>

char buf[1 << 21], *p1 = buf, *p2 = buf;
#ifndef ONLINE_JUDGE
#define gc() getchar()
#else
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
#endif
#define is_number (ch >= '0' && ch <= '9')

template < typename Type >
void read(Type& a) {
	a = 0; bool f = 0; char ch;
	while (!(ch = gc(), is_number)) if (ch == '-') f = 1;
	while (is_number) a = (a << 3) + (a << 1) + (ch ^ '0'), ch = gc();
	a = (f ? -a : a);
}

template < typename Type, typename... Args >
void read(Type& t, Args&... args) {
	read(t), read(args...);
}

int val[500005], f[500005][25];
int g[500005][25], vis[500005];
int n, m, d, tot, head[500005];
int nxt[1000005], to[1000005];
std::vector < std::vector < int > > G(500005);

void add(int x, int y) {
	to[++tot] = y;
	nxt[tot] = head[x];
	head[x] = tot;
	G[x].push_back(y);
	G[y].push_back(x);
}

void DP(int x, int fa) {
	if (vis[x]) g[x][0] = f[x][0] = val[x];
	for (int i = 1; i <= d; ++i) f[x][i] = val[x];
	f[x][d + 1] = 0x3f3f3f3f;
	for (int i = head[x]; i; i = nxt[i]) {
		int y = to[i];
		if (y ^ fa) {
			DP(y, x);
			for (int j = d; j >= 0; --j)
				f[x][j] = std::min(f[y][j + 1] + g[x][j + 1], f[x][j] + g[y][j]);
			for (int j = d; j >= 0; --j)
				f[x][j] = std::min(f[x][j + 1], f[x][j]);
			g[x][0] = f[x][0];
			for (int j = 1; j <= d + 1; ++j)
				g[x][j] += g[y][j - 1];
			for (int j = 1; j <= d + 1; ++j)
				g[x][j] = std::min(g[x][j - 1], g[x][j]);
		}
	}
}

signed main() {
	read(n, d);
	for (int i = 1; i <= n; ++i) read(val[i]);
	read(m);
	for (int i = 0, x; i < m; ++i) read(x), vis[x] = 1;
	for (int i = 1, x, y; i < n; ++i) read(x, y), add(x, y), add(y, x);
	DP(1, 0);
	printf("%d\n", g[1][0]);
}

Guess you like

Origin www.cnblogs.com/orchid-any/p/12731077.html