记录编号 546785 评测结果 AAAAAAAAAA
题目名称 [NOIP 2003]传染病控制 最终得分 100
用户昵称 Gravatar牛掰格拉斯 是否通过 通过
代码语言 C++ 运行时间 0.578 s
提交时间 2019-11-12 21:24:22 内存使用 13.68 MiB
显示代码纯文本
//2019.11.12
//方法:按层暴搜 
#include<bits/stdc++.h>
using namespace std;
const int N=400;
int n,p,ans,size[N];//人数,边数,答案,每个点节点个数 
bool vis[N],iscut[N];//判断该点是否被访问,和该点是否被隔离 
vector <int> dep[N];//存每一层的节点 
vector <int> tree[N];//存每个点的子节点 
void docut(int u)
{
	iscut[u]=true;
	for(int i=0;i<tree[u].size();i++)
	{
		int v=tree[u][i];
		docut(v);
	}
}
void uncut(int u)
{
	iscut[u]=false;
	for(int i=0;i<tree[u].size();i++)
	{
		int v=tree[u][i];
		uncut(v);
	}
}
int worksize(int u,int now)//预处理每一个节点的子节点数 
{ 
	vis[u]=true;
	dep[now].push_back(u);//将该节点存入该层 
	for(int i=0;i<tree[u].size();i++)
	{
		int v=tree[u][i];
		size[u]+=worksize(v,now+1); 
	} 
	return size[u];
}
void dfs(int l,int now)//当前层数,没有被隔离的总人数 
{
	for(int i=0;i<dep[l+1].size();i++)
	{
		int v=dep[l+1][i];
		if(iscut[v])	continue;
		docut(v);//将该点隔离 
		dfs(l+1,now-size[v]);//递归循环下一层 
		uncut(v);//回溯 
	}
	ans=min(ans,now);//在dfs中找没有被隔离总人数的最小值即为最优解 
}
int main()
{
	freopen("epidemic.in","r",stdin);
	freopen("epidemic.out","w",stdout);
	scanf("%d%d", &n, &p);
	ans=n;
	for(int i=1;i<=n;i++)	size[i]=1;
	for(int i=0;i<p;i++)
	{
		int x,y;
		scanf("%d%d", &x, &y);
		if(x>y)	swap(x,y);//???
		tree[x].push_back(y);
	} 
	worksize(1,1); 
	dfs(1,n); 
	printf("%d", ans);
	return 0;
}