传染病控制
传染病控制
sol:
pre:预处理G数组
G[i][j]表示深度为 i 的第 j 个节点
dfs(i)表示搜索到第 k 层的节点
记录一个数组,如果在u切断,那么s[u] = 2,如果父节点s[fa] = 2, 则令f[v] = 1,
表示该节点不用再切断
注意:搜索终止有两个条件,满足任意一个均可
1.到最后一层
2.完全切断病毒传播
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N = 3e2 + 100;
struct Edge {
int v, nxt;
} e[N << 1];
vector<int> G[N];
int s[N], head[N], dep[N], fa[N], siz[N];
int ans, n, cnt, mdep;
void AddEdge(int u, int v) {
e[++cnt].v = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
void pre(int u, int father) {
dep[u] = dep[father] + 1;
fa[u] = father;
siz[u] = 1;
mdep = max(mdep, dep[u]);
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].v;
if( v == father) continue;
pre(v, u);
siz[u] += siz[v];
}
}
void clear_subtree(int u) {
s[u] = 0;
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].v;
if( v == fa[u]) continue;
clear_subtree(v);
}
}
void dfs(int k, int victims) {
if(k == mdep + 1) {
if( victims > ans) {
ans = max(ans, victims);
// printf("%d\n", ans);
}
return;
}
int cnt = 0;
for(int i = 0; i < (int)G[k].size(); i ++) {
int u = G[k][i];
if( s[fa[u]] == 2 || s[fa[u]] == 1)
s[u] = 1, cnt ++;;
}
if( cnt == (int)G[k].size() ) {
if( victims > ans) {
ans = max(ans, victims);
// printf("%d\n", ans);
}
return;
}
for(int i = 0; i < (int)G[k].size(); i ++) {
int u = G[k][i];
if( s[u]) {
continue;
}
s[u] = 2;
dfs(k + 1, victims + siz[u]);
s[u] = 0;
clear_subtree(u);
}
}
int main()
{
int p;
scanf("%d%d", &n, &p);
for(int i = 1; i < n; i ++) {
int u, v;
scanf("%d%d", &u, &v);
AddEdge(u, v), AddEdge(v, u);
}
dep[0] = -1;
pre(1, 0);
for(int i = 1; i <= n; i ++)
G[dep[i]].push_back(i);
dfs(1, 0);
printf("%d\n", n - ans);
return 0;
}