[luoguP1041] 传染病控制(DFS)

传送门

 

n <= 300

结果裸的dfs就直接过了。。

枚举每一层,枚举删除每一层的边,然后把删除的边所连接的子树全部删去

 

代码

#include <vector>
#include <cstdio>
#include <cstring> 
#include <iostream>
#define N 301
#define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y))

int n, m, cnt, maxd, ans = ~(1 << 31);
int head[N], to[N << 1], next[N << 1], f[N], deep[N], size[N];
std::vector <int> vec[N];
bool vis[N];

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
	return x * f;
}

inline void add(int x, int y)
{
	to[cnt] = y;
	next[cnt] = head[x];
	head[x] = cnt++;
}

inline void dfs(int u)
{
	int i, v;
	size[u] = 1;
	maxd = max(maxd, deep[u] = deep[f[u]] + 1);
	vec[deep[u]].push_back(u);
	for(i = head[u]; i ^ -1; i = next[i])
	{
		v = to[i];
		if(v ^ f[u])
		{
			f[v] = u;
			dfs(v);
			size[u] += size[v];
		}
	}
}

inline void dfs2(int u, int x)
{
	int i, v;
	vis[u] = x;
	for(i = head[u]; i ^ -1; i = next[i])
	{
		v = to[i];
		if(v ^ f[u]) dfs2(v, x);
	}
}

inline void dfs1(int k, int sum)
{
	ans = min(ans, n - sum);
	if(k == maxd + 1) return;
	int i, x;
	for(i = 0; i < vec[k].size(); i++)
	{
		x = vec[k][i];
		if(!vis[x])
		{
			dfs2(x, 1);
			dfs1(k + 1, sum + size[x]);
			dfs2(x, 0);
		}
	}
}

int main()
{
	int i, x, y;
	n = read();
	m = read();
	memset(head, -1, sizeof(head));
	for(i = 1; i <= m; i++)
	{
		x = read();
		y = read();
		add(x, y);
		add(y, x);
	}
	dfs(1);
	dfs1(2, 0);
	printf("%d\n", ans);
	return 0;
}

  

posted @ 2017-07-01 16:01  zht467  阅读(162)  评论(0编辑  收藏  举报