传染病控制

传染病控制

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
", 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
", 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 - ans);
	return 0;
}
原文地址:https://www.cnblogs.com/wyy0804/p/13702020.html