Luogu1041 NOIP2003T4 傳染病控制 搜索
阿新 • • 發佈:2018-10-08
tar tle ont create getch 需要 lan col tor
題目傳送門:https://www.luogu.org/problemnew/show/P1041
題意:一棵有$N$個節點的有根樹的根節點($1$號點)出現了傳染病病毒,每一次你可以切斷樹上的一條邊,然後病毒就會沿著邊向葉子節點拓展一層,感染新一層節點,求最少有多少個節點被感染(1號節點最開始被感染)。$N \leq 300$
$15$年前的搜索題就是不一樣,暴搜加個最優化剪枝就能過$qwq$
根據貪心可以知道,每一次切斷的一條邊必定聯系最新被感染的節點和它的兒子,所以每一次只需要枚舉下面的哪個兒子不會被感染就可以了,復雜度$O($玄學$)$
1 #include<bits/stdc++.h>
2 using namespace std;
3 inline int read(){
4 int a = 0;
5 char c = getchar();
6 while(!isdigit(c)) c = getchar();
7 while(isdigit(c)) a = (a << 3) + (a << 1) + (c ^ 48) , c = getchar();
8 return a;
9 }
10 inline int min(int a , int b){
11 return a < b ? a : b;
12 }
13 vector < int > Ed[301];
14 queue < int > q;
15 int minN = 0x3f3f3f3f;
16 bool vis[301];
17 void choose(int , queue < int >);
18 void create(int num , queue < int > q){
19 queue < int > q1;
20 register int sum = 0;
21 while(!q.empty()){
22 int t = q.front();
23 q.pop();
24 num++;
25 for(register int i = 0 ; i < Ed[t].size() ; i++)
26 if(!vis[Ed[t][i]]){
27 q1.push(Ed[t][i]);
28 if(num + ++sum > minN) return;
29 }
30 }
31 if(num + sum > minN) return;
32 if(sum == 0){
33 minN = min(minN , num);
34 return;
35 }
36 choose(num , q1);
37 }
38 int main(){
39 register int n = read() , p = read();
40 for(register int i = 0 ; i - p ; i++){
41 int a = read() , b = read();
42 Ed[a].push_back(b);
43 Ed[b].push_back(a);
44 }
45 q.push(1);
46 vis[1] = 1;
47 create(0 , q);
48 printf("%d" , minN);
49 return 0;
50 }
51 void choose(int num , queue < int > q){
52 register int first = q.front();
53 do{
54 vis[q.front()] = 1;
55 q.push(q.front());
56 q.pop();
57 }while(q.front() - first);
58 do{
59 register int t = q.front();
60 q.pop();
61 create(num , q);
62 q.push(t);
63 }while(q.front() - first);
64 while(!q.empty()){
65 vis[q.front()] = 0;
66 q.pop();
67 }
68 }
Luogu1041 NOIP2003T4 傳染病控制 搜索