noip2003 传染病防治

题目是给出一棵树(以1为根),每一次只在当前一层删掉一条边,每次病毒会扩散一层,求最小扩散到的节点数。

一开始想到贪心,删去儿子的子节点个数最小的点和根的连边,利用深搜。

但这样只有70分。。。

procedure dfs(x:longint);
var flag:boolean;
    max:longint;
i,j,k:longint;
begin
 flag:=false;//标记有没有可找的,看传染是否结束
 max:=-1;
 for i:=1 to son[x] do //贪心,找儿子中儿子个数最大的删去
   if son[c[x,i]]>max then 
    begin
max:=son[c[x,i]];
j:=c[x,i];
end;
 son[j]:=0;
 if son[x]>0 then ans:=ans+son[x]-1; 
 for i:=1 to son[x] do//把要删去的子节点的兄弟的儿子变为它的子节点
  if c[x,i]<>j then 
    for k:=1 to son[c[x,i]] do
begin 
 son[j]:=son[j]+1;
 c[j,son[j]]:=c[c[x,i],k];
 flag:=true;
end;
 if flag then dfs(j);
 if flag=false then 
  begin 
   if ans<min then min:=ans;
   exit;
 end;
end;

问题出在可能子节点最多的那个儿子后面的情况并不优,具有后效性。

从这题程序学到的:①给出边的关系,还要自己递归建树,因为给的边不一定有顺序,很容易挂。

                                    ②像这种树的关系判断是否到达最后一层,可以用flag标记,如果当前节点没有儿子,就可以比较最优解了。

var n,p,i,x,y,s,ans:longint;
    son,deep:array[1..300]of longint;
	c,a:array[1..300,1..300]of longint;
	f:array[1..300]of boolean;
procedure init;
begin
 read(n,p);
 for i:=1 to p do
  begin
   read(x,y);
   a[x,y]:=1;a[y,x]:=1;
  end;
end;
procedure buildtree(x:longint);
var i:longint;
begin
 f[x]:=false;
 for i:=1 to n do
  if (a[x,i]=1)and(f[i]) then 
   begin
    son[x]:=son[x]+1;
	c[x,son[x]]:=i;
	buildtree(i);
   end;
end;
procedure dfs(x:longint);//每次搜索一层,回溯的时候要恢复为没有搜过的
var flag:boolean;
    i,j,tmp:longint;
begin
 if s>ans then exit;//剪枝
 flag:=false;
 tmp:=s;//用于恢复
 for i:=1 to n do
  if deep[i]=x then //按层搜索,可以每次循环找一层的枚举
   for j:=1 to son[i] do
    begin
	 deep[c[i,j]]:=x+1;
	 flag:=true;
	 s:=s+1;//其他儿子
	end;
 if flag=false then//搜到的这层都没有点了,表示一种可能遍历完成 
  begin 
   if ans>s then ans:=s;
   exit;
  end;
 s:=s-1;//要删的点
 for i:=1 to n do 
  if deep[i]=x+1 then 
   begin 
    deep[i]:=0;//删这个点
    dfs(x+1);
	deep[i]:=x+1;
   end;
 s:=tmp;
 for i:=1 to n do if deep[i]=x+1 then deep[i]:=0;//每一层的恢复
end;
begin
 init;
 fillchar(f,sizeof(f),true);
 fillchar(s,sizeof(s),0);
 fillchar(c,sizeof(c),0);
 buildtree(1);
 deep[1]:=1;
 ans:=maxlongint;
 s:=1;
 dfs(1);
 writeln(ans);
end.

    原文作者:传染病问题
    原文地址: https://blog.csdn.net/zz_ylolita/article/details/40396933
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞