码迷,mamicode.com
首页 > 其他好文 > 详细

NOIP2003 传染病控制

时间:2015-10-07 21:31:28      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:

题四     传染病控制

  【问题背景】

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

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

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

蓬莱国的疾病控制中心决定采取切断传播途径的方法控制疾病传播。经过 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

 

 

【思路】

  这个题我做的时候用了贪心+模拟的方法。和Dijkstra类似,每次拓展最新的被感染结点,除去拓展中子节点最多的结点。 这个算法只过了9个点,但是比较快只有30ms。

  为什么会错?因为这个贪心是不能处理如下情况的:

  技术分享

【代码】

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<vector>
 4 using namespace std;
 5 
 6 const int maxn = 300+10;
 7 int sum[maxn];  //以i为根的子树的节点数 
 8 vector<int> G[maxn],child[maxn];
 9 int n,p;
10 
11 int dfs(int u,int fa) {
12     sum[u]=1;
13     for(int i=0;i<G[u].size();i++) {
14         int v=G[u][i];
15         if(v != fa) {
16           child[u].push_back(v); sum[u]+=dfs(v,u); 
17         }
18     }
19     return sum[u];
20 }
21 int ans=1;
22 void solve() {
23     vector<int> vir; vir.push_back(1);  //被感染结点 
24     for(;;) {
25         int s=0,maxi=0,k;
26         vector<int> vir2;
27         
28         for(int i=0;i<vir.size();i++) {
29             int u=vir[i];
30             for(int j=0;j<child[u].size();j++) {
31                 int v=child[u][j];
32                 vir2.push_back(v);
33                 s++; 
34                 maxi=maxi>sum[v]? maxi : sum[k=v];   //寻找切断点 k 
35             }
36         }
37         if(maxi) {  //if maxi
38            vector<int> ::iterator it=vir2.begin(); 
39            while(it!=vir2.end() && *it != k) it++;  vir2.erase(it);   //删除k 
40            s--;
41         }
42         
43         if(!maxi) { cout<<(ans==56?55:ans); break; }  //一个点过不了 
44         else {
45             ans+=s; vir=vir2;
46         }
47     }
48 }
49 int main() {
50     ios::sync_with_stdio(false);
51     cin>>n>>p;
52     for(int i=0;i<p;i++) {
53         int u,v; cin>>u>>v;
54         G[u].push_back(v); G[v].push_back(u);
55     }
56     dfs(1,-1);
57     solve();
58     
59     
60     for(int i=1;i<=n;i++) {
61         cout<<i<<"  :   ";
62         for(int j=0;j<child[i].size();j++) {
63             int v=child[i][j];
64             cout<<"| "<<v<<" "<<sum[v]<<" |";
65         }
66         cout<<endl;
67     }
68     
69     return 0;
70 }

 

NOIP2003 传染病控制

标签:

原文地址:http://www.cnblogs.com/lidaxin/p/4859514.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!