首页 > 代码库 > [NOIP2003] 传染病控制题解
[NOIP2003] 传染病控制题解
问题 F: [NOIP2003] 传染病控制
时间限制: 1 Sec 内存限制: 128 MB题目描述
【问题背景】
近来,一种新的传染病肆虐全球。蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府 决定不惜一切代价控制传染病的蔓延。不幸的是,由于人们尚未完全认识这种传染病,难以准确判别病毒携带者,更没有研制出疫苗以保护易感人群。于是,蓬莱国 的疾病控制中心决定采取切断传播途径的方法控制疾病传播。经过 WHO (世界卫生组织)以及全球各国科研部门的努力,这种新兴传染病的传播途径和控制方法已经研究消除,剩下的任务就是由你协助蓬莱国疾控中心制定一个有效的控 制办法。
【问题描述】
研究表明,这种传染病的传播具有两种很特殊的性质;第一是它的 传播途径是树型的,一个人 X 只可能被某个特定的人 Y 感染,只要 Y 不得病,或者是 XY 之间的传播途径被切断,则 X 就不会得病。第二是,这种疾病的传播有周期性,在一个疾病传播周期之内,传染病将只会感染一代患者,而不会再传播给下一代。
这 些性质大大减轻了蓬莱国疾病防控的压力,并且他们已经得到了国内部分易感人群的潜在传播途径图(一棵树)。但是,麻烦还没有结束。由于蓬莱国疾控中心人手 不够,同时也缺乏强大的技术,以致他们在一个疾病传播周期内,只能设法切断一条传播途径,而没有被控制的传播途径就会引起更多的易感人群被感染(也就是与 当前已经被感染的人有传播途径相连,且连接途径没有被切断的人群)。当不可能有健康人被感染时,疾病就中止传播。所以,蓬莱国疾控中心要制定出一个切断传 播途径的顺序,以使尽量少的人被感染。
你的程序要针对给定的树,找出合适的切断顺序。
输入
输入格式的第一行是两个整数 n ( 1≤n≤300 )和 p 。接下来 p 行,每一行有两个整数 i 和 j ,表示节点 i 和 j 间有边相连(意即,第 i 人和第 j 人之间有传播途径相连)。其中节点1 是已经被感染的患者。
输出
只有一行,输出总共被感染的人数。
样例输入
7 6
1 2
1 3
2 4
2 5
3 6
3 7
样例输出
3
这道题总体来看还是算比较容易的一类爆搜题,可以打贪心去优化,但只有贪心是不对的,虽然貌似只WA一个点,但也只是数据水,尽管董学长的“估价函数”可以卡过,但也只是针对这一个数据,很容易举出反例,因此不多赘述。
这道题基本一个深搜就可以搞定,我是先维护一个队列,表示在下一个周期中可能会被感染的点,然后将队列复制,挨个去枚举其中因被控制而没被感染的点,然后挨个深搜,时间虽然比贪心慢了不少,但其实也是无伤大雅的,至少只要是合法数据就一定卡不到它。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<map> 7 #include<queue> 8 #include<string> 9 #include<cmath> 10 using namespace std; 11 int n,p,zz; 12 struct ro{ 13 int to; 14 int next; 15 int from; 16 int bh,size; 17 }road[900]; 18 int a[350]; 19 void build(int x,int y){ 20 zz++; 21 road[zz].bh=zz; 22 road[zz].to=y; 23 road[zz].from=x; 24 road[zz].next=a[x]; 25 a[x]=zz; 26 } 27 int fa[350],son[350],ans=0x7fffffff; 28 void dfs1(int x){ 29 for(int i=a[x];i>0;i=road[i].next) 30 { 31 int y=road[i].to; 32 if(y!=fa[x]) 33 { 34 son[x]++; 35 fa[y]=x; 36 dfs1(y); 37 road[i].size=son[y]; 38 } 39 } 40 } 41 int q[9000],head,en; 42 void bfs(int js){ 43 if(js>=ans) return; 44 int qq[9000],hea=head,ed=en; 45 memcpy(qq,q,sizeof(q)); 46 int jj=js; 47 for(int i=hea;i<=ed;i++) 48 { 49 js=jj; 50 head=1,en=0; 51 memset(q,0,sizeof(q)); 52 for(int j=hea;j<=ed;j++) 53 { 54 if(i==j) continue; 55 js++; 56 for(int k=a[qq[j]];k>0;k=road[k].next) 57 { 58 int y=road[k].to; 59 if(y!=fa[qq[j]]) 60 { 61 en++; 62 q[en]=y; 63 } 64 } 65 } 66 if(js>ans) 67 return; 68 if(en==0) 69 { 70 ans=min(ans,js); 71 return; 72 } 73 if(js!=jj) bfs(js); 74 } 75 76 } 77 int main(){ 78 freopen("epidemic.in","r",stdin); 79 freopen("epidemic.out","w",stdout); 80 scanf("%d%d",&n,&p); 81 for(int i=1;i<=p;i++) 82 { 83 int x,y; 84 scanf("%d%d",&x,&y); 85 build(x,y); 86 build(y,x); 87 } 88 dfs1(1); 89 head=1; 90 cout<<endl; 91 for(int i=a[1];i>0;i=road[i].next) 92 { 93 int y=road[i].to; 94 en++; 95 q[en]=y; 96 } 97 bfs(1); 98 printf("%d\n",ans); 99 //while(1); 100 return 0; 101 }
[NOIP2003] 传染病控制题解
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。