[NOIP2003]传染病控制【搜索】

本文探讨了一种新型传染病在蓬莱国的传播特性与控制方法。基于疾病传播的特殊性,包括树状传播路径与周期性感染特点,提出通过合理切断传播途径以最小化感染人数的有效策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【问题背景】

   近来,一种新的传染病肆虐全球。蓬莱国也发现了零星感染者,为防止该病在蓬莱国

大范围流行,该国政府决定不惜一切代价控制传染病的蔓延。不幸的是,由于人们尚未完

全认识这种传染病,难以准确判别病毒携带者,更没有研制出疫苗以保护易感人群。于是,

蓬莱国的疾病控制中心决定采取切断传播途径的方法控制疾病传播。经过 WHO(世界卫

生组织)以及全球各国科研部门的努力,这种新兴传染病的传播途径和控制方法已经研究

消楚,剩下的任务就是由你协助蓬莱国疾控中心制定一个有效的控制办法。

 

  【问题描述】

   研究表明,这种传染病的传播具有两种很特殊的性质;

   第一是它的传播途径是树型的,一个人X只可能被某个特定的人Y感染,只要Y不

得病,或者是XY之间的传播途径被切断,则X就不会得病。

   第二是,这种疾病的传播有周期性,在一个疾病传播周期之内,传染病将只会感染一

代患者,而不会再传播给下一代。

   这些性质大大减轻了蓬莱国疾病防控的压力,并且他们已经得到了国内部分易感人群

的潜在传播途径图(一棵树)。但是,麻烦还没有结束。由于蓬莱国疾控中心人手不够,同

时也缺乏强大的技术,以致他们在一个疾病传播周期内,只能设法切断一条传播途径,而

没有被控制的传播途径就会引起更多的易感人群被感染(也就是与当前已经被感染的人有

传播途径相连,且连接途径没有被切断的人群)。当不可能有健康人被感染时,疾病就中止

传播。所以,蓬莱国疾控中心要制定出一个切断传播途径的顺序,以使尽量少的人被感染。

你的程序要针对给定的树,找出合适的切断顺序。

 

【输入格式】

   输入格式的第一行是两个整数n(1≤n≤300)和p。接下来p行,每一行有两个整数i

和j,表示节点i和j间有边相连(意即,第i人和第j人之间有传播途径相连)。其中节点

1是已经被感染的患者。

 

【输出格式】

   只有一行,输出总共被感染的人数。

解题思路:这题一开始想的是贪心,,不过好像有后效性,会找到反例。。正确的解法是搜索,如题意我们要做的就是每一层剪掉一条边,所以只要回溯搜索每一层剪掉的边就可以了。可以加上最优性剪枝减少一些时间:若当前感染人数已经超过当前更新到的最大答案,显然不需要再往下搜了。

 

代码:

#include
#include
#include
using namespace std;
struct point{
int e;
point *next;
};
point *a[305]={0},*pp,*p1;
int que[305],u[305]={0},i,n,p,minans,len,e,s;
void dfs(int k,int que[],int len,int now)
{if (now+len-1>=minans) return;
//cout<<len<<endl;
if (len==0) {if (now
if (now>=minans) return;
int i,que1[305],len1=0;
point *p;
p=(point*)malloc(sizeof(point));
for (i=1;i<=len;i++)
 if (i!=k) {p=a[que[i]];
 while (p!=0){len1++;que1[len1]=p->e;p=p->next;}
 }
//printf("%d*\n",len1);
if (len1==0) {if (now+len-1
for (i=1;i<=len1;i++)
 dfs(i,que1,len1,now+len-1);
}
int main(){
freopen("bin.txt","r",stdin);
scanf("%d%d",&n,&p);
u[1]=1;
for (i=1;i<=p;i++)
{scanf("%d%d",&s,&e);
if (u[e]==1) swap(s,e);
pp=(point*)malloc(sizeof(point));
pp->e=e;
pp->next=a[s];
a[s]=pp;
u[e]=1;
}
p1=(point*)malloc(sizeof(point));
p1=a[1];minans=1111111;
while (p1!=0) {len++;que[len]=p1->e;p1=p1->next;}
for (i=1;i<=len;i++)
 dfs(i,que,len,1);
printf("%d",minans);
fclose(stdin);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值