1.读入图,边是双向的
2.递归建树,同时确定每一层的节点
3.dfs按层搜索,先把这一层所有被传染的(die[pa[k]]=true的)的die置为true
然后循环,每次把一个die为true的变为false,表示断开这条边,继续dfs
dfs的最后记得把这一层die的全部置为false(查了一下午...)
退出条件:now当前死的人>=ans, f当前层>layerNum,num这一层死的人==0
代码:
#include<iostream> #define Size 305 #define INF 10000000 using namespace std; int n; int g[Size][Size]; int layer[Size][Size]; int pa[Size]; bool vis[Size]; bool die[Size]; int ans=INF; int layerNum=0; int way[Size]; void buildTree(int k,int f){ vis[k]=true; layer[f][++layer[f][0]]=k; if(f>layerNum)layerNum=f; for(int i=1;i<=g[k][0];i++){ int s=g[k][i]; if(!vis[s]){ pa[s]=k; buildTree(s,f+1); } } } void dfs(int f,int now){//f:layer if(now>=ans)return; if(f>layerNum){ ans=min(now,ans); /*cout<<ans<<": "; for(int i=1;i<=layerNum;i++)cout<<way[i]<<' '; cout<<endl;*/ return; } int num=0; for(int i=1;i<=layer[f][0];i++){ int k=layer[f][i]; if(die[pa[k]])die[k]=true,num++; } if(num==0){ ans=min(now,ans); return; } for(int i=1;i<=layer[f][0];i++){ int k=layer[f][i]; if(die[k]){ way[f]=k; die[k]=false; dfs(f+1,now+num-1); die[k]=true; } } for(int i=1;i<=layer[f][0];i++){//退出之前清零当前层的die die[layer[f][i]]=false; } } int main(){ freopen("1091.in","r",stdin); int p,a,b; cin>>n>>p; for(int i=1;i<=p;i++){ cin>>a>>b; g[a][++g[a][0]]=b; g[b][++g[b][0]]=a; } buildTree(1,1); /*for(int i=1;i<=layerNum;i++){ for(int j=1;j<=layer[i][0];j++) cout<<layer[i][j]<<' '; cout<<endl; }*/ die[1]=true; dfs(2,1); cout<<ans<<endl; fclose(stdin); return 0; }