1. 程式人生 > >P1041 傳染病控制(dfs)

P1041 傳染病控制(dfs)

bit 兩種 -a fine 組織 決定 ems center -html

P1041 傳染病控制

題目背景

近來,一種新的傳染病肆虐全球。蓬萊國也發現了零星感染者,為防止該病在蓬萊國大範圍流行,該國政府決定不惜一切代價控制傳染病的蔓延。不幸的是,由於人們尚未完全認識這種傳染病,難以準確判別病毒攜帶者,更沒有研制出疫苗以保護易感人群。於是,蓬萊國的疾病控制中心決定采取切斷傳播途徑的方法控制疾病傳播。經過 WHOWHO(世界衛生組織)以及全球各國科研部門的努力,這種新興傳染病的傳播途徑和控制方法已經研究清楚,剩下的任務就是由你協助蓬萊國疾控中心制定一個有效的控制辦法。

題目描述

研究表明,這種傳染病的傳播具有兩種很特殊的性質;

第一是它的傳播途徑是樹型的,一個人XX只可能被某個特定的人YY感染,只要YY不得病,或者是XYXY之間的傳播途徑被切斷,則XX就不會得病。

第二是,這種疾病的傳播有周期性,在一個疾病傳播周期之內,傳染病將只會感染一代患者,而不會再傳播給下一代。

這些性質大大減輕了蓬萊國疾病防控的壓力,並且他們已經得到了國內部分易感人群的潛在傳播途徑圖(一棵樹)。但是,麻煩還沒有結束。由於蓬萊國疾控中心人手不夠,同時也缺乏強大的技術,以致他們在一個疾病傳播周期內,只能設法切斷一條傳播途徑,而沒有被控制的傳播途徑就會引起更多的易感人群被感染(也就是與當前已經被感染的人有傳播途徑相連,且連接途徑沒有被切斷的人群)。當不可能有健康人被感染時,疾病就中止傳播。所以,蓬萊國疾控中心要制定出一個切斷傳播途徑的順序,以使盡量少的人被感染。

你的程序要針對給定的樹,找出合適的切斷順序。

輸入輸出格式

輸入格式:

輸入格式:
第一行是兩個整數n(1≤n≤300)n(1n300)和pp。
接下來pp行,每一行有22個整數ii和jj,表示節點ii和jj間有邊相連。(意即,第ii人和第jj人之間有傳播途徑相連)。其中節點11是已經被感染的患者。

輸出格式:

11行,總共被感染的人數。

輸入輸出樣例

輸入樣例#1: 復制
7 6
1 2
1 3
2 4
2 5
3 6
3 7
輸出樣例#1: 復制
//https://blog.csdn.net/wyxeainn/article/details/57087108
#include<bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; vector<int> v[310],t[310]; int level[310]; int vis[310]; int m,n,total,ans; void create_tree(int node) ///構建有向樹 { vis[node] = 1; //將節點node標記 for(int i = 0; i < v[node].size(); i++) //size函數求出node容器中的元素個數,即與node相鄰的節點 { if(vis[v[node][i]]==0) { t[node].push_back(v[node][i]); create_tree(v[node][i]); } } } void dfs(int le) //一層一層地向下遞歸,初始level為1 { int child = 0; //child變量用來標記level+1層有沒有節點,如果有,child=1 if(ans <= total) return; //如果當前情況患病人數比最佳答案ans多或相等,則直接return for(int i = 1; i <= m; i++) //共有m個人即m個節點,找出在le層的節點 { if(level[i]==le) { for(int j = 0; j < t[i].size(); j++) { child = 1; //代表第le+1層上有節點 total++; //將le+1層上的節點數加到total上 level[t[i][j]]=le+1; //節點i的孩子的level值賦為le+1 } } }//到此位置total是沒有斷開情況下,所有的患病人數 if(child==0) ///如果第le+1層沒有節點,遞歸結束條件之1 { ans = min(ans,total); //獲取ans和total的最小值 return; } else { total--; //每一輪傳播都可以選擇一個節點與它的父節點斷開,則患病人數少1,total減減 for(int i = 1; i <= m; i++) { if(level[i]==le+1) //如果節點i在le+1層上,假如切斷的節點是i與它前驅間的那條路 { level[i]=0; ///則將level[i]賦為0,則下次深搜便不會再考慮這個節點以及該節點的子節點。因為level[i]=0!=le+1 dfs(le+1); /// 搜索第le+1層 level[i]=le+1; ///回溯恢復原值 } } total++; //回溯,恢復到沒有切斷路的狀態,則被傳染的人增加1 for(int i = 1; i <= m; i++) //到此,第le+1層都已經遞歸求過了。 { if(level[i]==le+1) { level[i]=0; //將節點i的層數賦為0 total--; } } } } int main() { int i,a,b; ///m個人,n個關系 while(~scanf("%d%d",&m,&n)) { memset(vis,0,sizeof(vis)); for(i = 1;i <= m; i++) { v[i].clear(); //清空容器 t[i].clear(); } for(i = 1; i <= n; i++) { scanf("%d%d",&a,&b); v[a].push_back(b); v[b].push_back(a); } total = 1; ans = INF; create_tree(1) ; //構建有向樹 level[1]=1; dfs(1); printf("%d\n",ans); } return 0; }

P1041 傳染病控制(dfs)