P1041 传染病控制
标签
相关讨论
推荐题目
题目背景
本题是错题,后来被证明没有靠谱的多项式复杂度的做法。测试数据非常的水,各种玄学做法都可以通过,不代表算法正确。因此本题题目和数据仅供参考。
近来,一种新的传染病肆虐全球。蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延。不幸的是,由于人们尚未完全认识这种传染病,难以准确判别病毒携带者,更没有研制出疫苗以保护易感人群。于是,蓬莱国的疾病控制中心决定采取切断传播途径的方法控制疾病传播。经过 WHO(世界卫生组织)以及全球各国科研部门的努力,这种新兴传染病的传播途径和控制方法已经研究清楚,剩下的任务就是由你协助蓬莱国疾控中心制定一个有效的控制办法。
题目描述
研究表明,这种传染病的传播具有两种很特殊的性质;
第一是它的传播途径是树型的,一个人 XXX 只可能被某个特定的人 YYY 感染,只要 YYY 不得病,或者是 XYXYXY 之间的传播途径被切断,则 XXX 就不会得病。
第二是,这种疾病的传播有周期性,在一个疾病传播周期之内,传染病将只会感染一代患者,而不会再传播给下一代。
这些性质大大减轻了蓬莱国疾病防控的压力,并且他们已经得到了国内部分易感人群的潜在传播途径图(一棵树)。但是,麻烦还没有结束。由于蓬莱国疾控中心人手不够,同时也缺乏强大的技术,以致他们在一个疾病传播周期内,只能设法切断一条传播途径,而没有被控制的传播途径就会引起更多的易感人群被感染(也就是与当前已经被感染的人有传播途径相连,且连接途径没有被切断的人群)。当不可能有健康人被感染时,疾病就中止传播。所以,蓬莱国疾控中心要制定出一个切断传播途径的顺序,以使尽量少的人被感染。
你的程序要针对给定的树,找出合适的切断顺序。
输入格式
输入格式:
第一行是两个整数 nnn 和 ppp。
接下来 ppp 行,每一行有 222 个整数 iii 和 jjj,表示节点 iii 和 jjj 间有边相连。(意即,第 iii 人和第 jjj 人之间有传播途径相连)。其中节点 111 是已经被感染的患者。
输出格式
111 行,总共被感染的人数。
输入输出样例
7 6 1 2 1 3 2 4 2 5 3 6 3 7
3
说明/提示
对于 100%100\%100% 的数据,1≤n≤3001 \leq n \leq 3001≤n≤300。
思路
枚举可以砍的边,在砍的时候剪枝,对于一棵子树来说,如果砍掉一条边,则那条边下面的所有边都无法被访问到,在砍掉的同时标记其下所有的边,就可以避免重复枚举。
CODE
1 #include <bits/stdc++.h> 2 #define dbg(x) cout << #x << "=" << x << endl 3 4 using namespace std; 5 typedef long long LL; 6 7 template<class T>inline void read(T &res) 8 { 9 char c;T flag=1; 10 while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0'; 11 while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag; 12 } 13 14 namespace _buff { 15 const size_t BUFF = 1 << 19; 16 char ibuf[BUFF], *ib = ibuf, *ie = ibuf; 17 char getc() { 18 if (ib == ie) { 19 ib = ibuf; 20 ie = ibuf + fread(ibuf, 1, BUFF, stdin); 21 } 22 return ib == ie ? -1 : *ib++; 23 } 24 } 25 26 int qread() { 27 using namespace _buff; 28 int ret = 0; 29 bool pos = true; 30 char c = getc(); 31 for (; (c < '0' || c > '9') && c != '-'; c = getc()) { 32 assert(~c); 33 } 34 if (c == '-') { 35 pos = false; 36 c = getc(); 37 } 38 for (; c >= '0' && c <= '9'; c = getc()) { 39 ret = (ret << 3) + (ret << 1) + (c ^ 48); 40 } 41 return pos ? ret : -ret; 42 } 43 44 const int maxn = 310; 45 46 int n,m,ans; 47 int cnt = 0; 48 49 vector <int> level[maxn << 2]; 50 int sz[maxn]; 51 int edge[maxn <<2]; 52 int nxt[maxn << 2]; 53 int color[maxn << 2]; 54 int head[maxn << 2]; 55 56 void BuildGraph(int u, int v) { 57 edge[cnt] = v; 58 nxt[cnt] = head[u]; 59 head[u] = cnt++; 60 } 61 62 int dfs_level(int u, int depth, int pre) { 63 //dbg(u); 64 //dbg(depth); 65 sz[u] = 1; 66 for(int i = head[u]; ~i; i = nxt[i]) { 67 int v = edge[i]; 68 //dbg(i),dbg(v); 69 if(v == pre) { 70 continue; 71 } 72 sz[u] += dfs_level(v, depth+1, u); 73 level[depth].push_back(i); 74 } 75 return sz[u]; 76 } 77 78 void dfs_draw(int u, int cl) { 79 //dbg(u); 80 color[u] = cl; 81 int v = edge[u]; 82 for(int i = head[v]; ~i; i = nxt[i]) { 83 //int v = edge[i].to; 84 if(i == (u^1)) continue; 85 dfs_draw(i,cl); 86 } 87 } 88 89 void dfs(int u, int s) { 90 //dbg(u); 91 ans = min(ans, s); 92 int d = level[u].size(); 93 for(int i = 0; i < d; ++i) { 94 int v = level[u][i]; 95 if(!color[v]) { 96 dfs_draw(v,1); 97 dfs(u+1, s-sz[edge[v]]); 98 dfs_draw(v,0); 99 } 100 } 101 } 102 103 int main() 104 { 105 scanf("%d %d",&n, &m); 106 memset(head,-1,sizeof(head)); 107 ans = n; 108 for(int i = 1; i <= m; ++i) { 109 int u,v; 110 scanf("%d %d",&u, &v); 111 BuildGraph(u,v); 112 BuildGraph(v,u); 113 } 114 dfs_level(1,0,-1); 115 dfs(0,ans); 116 cout << ans << endl; 117 return 0; 118 }