传染病控制
由于题给数据量较小,所以暴力搜索很容易过
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<stack>
#include<vector>
#include<map>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int num[500];//存储节点数
int deeper[500][500];//存储深度及编号
int vis[500];
int deepers=0,n,m,ans=1000;
vector<int>E[500];//存边
struct edge
{
int from,to,val;
}h;
int Count(int tree)//统计节点数
{
int sz=E[tree].size();
for(int i=0;i<sz;i++)
{
num[tree]+=Count(E[tree][i]);
}
return num[tree];
}
void Deep(int tree,int deep)//上一层的根节点,这一层的深度
{
deepers=max(deepers,deep);
int sz=E[tree].size();
for(int i=0;i<sz;i++)
{
deeper[deep][0]++;
deeper[deep][deeper[deep][0]]=E[tree][i];
Deep(E[tree][i],deep+1);
}
return ;
}
void work(int tree,int trag)//为了避免同一深度搜索时重复
{
int sz=E[tree].size();
for(int i=0;i<sz;i++)
{
vis[E[tree][i]]=trag;
work(E[tree][i],trag);
}
return ;
}
void dfs(int deep,int cnt)//感染数目
{
if(deep==deepers)
{
ans=min(ans,cnt);
return;
}
int flag=0;
for(int i=0;i<deeper[deep][0];i++)
{
if(vis[deeper[deep][i+1]])
{
flag++;
continue;
}
vis[deeper[deep][i+1]]=1;//标记根节点,并标记相应所有子节点
work(deeper[deep][i+1],1);
dfs(deep+1,cnt-num[deeper[deep][i+1]]);
vis[deeper[deep][i+1]]=0;
work(deeper[deep][i+1],0);
}
if(flag==deeper[deep][0])//当同一深度都被标记则感染完毕更新感染数目
ans=min(ans,cnt);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for(int i=0;i<m;i++)
{
int u,v;
cin>>u>>v;
E[min(u,v)].push_back(max(u,v));
}
for(int i=1;i<=n;i++) num[i]=1;//初始化数目
Count(1);
Deep(1,2);
dfs(2,n);
cout<<ans<<endl;
}