题目地址

题目链接

题解

这里讲一个非正解——贪心+随机化

贪心的想法是什么?

我们dfs一遍处理出每个节点子树内的节点数量,记为\(siz\)。

贪心的砍掉\(siz\)最大的那个子树,在树的形态比较正常的情况下是可以得到最优解的。

如何hack掉这种贪心?

构造一条链,在中间的地方放一个“很胖”的分支,可以只分两层,每层的节点构造多一些(注意要使这个分支的节点数量小于链下半部分的节点数量)

这样子我们按照上述贪心,将会得到错误的结果,更优的做法是把这个分支直接砍掉(因为链上每次传染只会增加一个被传染的人)

当然,实际构造可以更加复杂,这只是最极端的情况。

不过,这种错误的贪心已经可以得到90分了。

如何得到满分?

要对答案产生影响,那么需要的那个分支的大小就不会太小(因为实际情况下一般是不会像上面那样子构造的,毒瘤出题人除外)

我们采用随机化的思想(实际上下面这个随机化的方法并不好,不过数据水也就水过去了)。

我们定义一种判定规则,如果某个节点恰好符合这个判定规则(一般是随机的),那么就改变原本的贪心策略,换用另外一个策略。

这里用的判定规则是rand出来的结果对233取模是否为0.

如果符合这个判定规则的话,我们就选择子树大小第二大(这个使用优先队列实现)的子树砍掉。

当然,这很不靠谱。

通常的做法是在不TLE的情况下尽量跑多次(能多少次就多少次),对所有结果取min。

所以随机化能水过去一般靠大量的尝试,尽量靠谱的判定规则,以及另外一个策略靠不靠谱。。。

注意,在此题中,需要使判定成功的可能性尽可能低,当然也不能太低

下面给出代码,注意,因为代码里只跑了200次进行尝试,不保证一定能ac,可以自行调大次数,或者多交几次(我交了2发才过)。

  1. #include <bits/stdc++.h>
  2. #define ll long long
  3. #define inf 0x3f3f3f3f
  4. #define il inline
  5. namespace io {
  6. #define in(a) a=read()
  7. #define out(a) write(a)
  8. #define outn(a) out(a),putchar('\n')
  9. #define I_int ll
  10. inline I_int read() {
  11. I_int x = 0 , f = 1 ; char c = getchar() ;
  12. while( c < '0' || c > '9' ) { if( c == '-' ) f = -1 ; c = getchar() ; }
  13. while( c >= '0' && c <= '9' ) { x = x * 10 + c - '0' ; c = getchar() ; }
  14. return x * f ;
  15. }
  16. char F[ 200 ] ;
  17. inline void write( I_int x ) {
  18. if( x == 0 ) { putchar( '0' ) ; return ; }
  19. I_int tmp = x > 0 ? x : -x ;
  20. if( x < 0 ) putchar( '-' ) ;
  21. int cnt = 0 ;
  22. while( tmp > 0 ) {
  23. F[ cnt ++ ] = tmp % 10 + '0' ;
  24. tmp /= 10 ;
  25. }
  26. while( cnt > 0 ) putchar( F[ -- cnt ] ) ;
  27. }
  28. #undef I_int
  29. }
  30. using namespace io ;
  31. using namespace std ;
  32. #define N 310
  33. int n, m, f[N];
  34. int cnt, head[N], siz[N], fa[N];
  35. struct edge {
  36. int to, nxt;
  37. }e[N<<1];
  38. void ins(int u, int v) {
  39. e[++cnt] = (edge) {v, head[u]};
  40. head[u] = cnt;
  41. }
  42. void dfs(int u) {
  43. siz[u] = 1;
  44. for(int i = head[u]; i; i = e[i].nxt) {
  45. if(e[i].to == fa[u]) continue;
  46. fa[e[i].to] = u;
  47. dfs(e[i].to);
  48. siz[u] += siz[e[i].to];
  49. }
  50. }
  51. struct Node {
  52. int val;
  53. };
  54. priority_queue<Node> q, t;
  55. bool operator < (Node a, Node b) {
  56. return siz[a.val] < siz[b.val];
  57. }
  58. int solve() {
  59. while(!q.empty()) q.pop();
  60. int ans = 0;
  61. q.push((Node){1});
  62. while(!q.empty()) {
  63. int cur = 0;
  64. while(!t.empty()) t.pop();
  65. while(!q.empty()) {
  66. int u = q.top().val; ++ans;
  67. for(int i = head[u]; i; i = e[i].nxt) {
  68. if(e[i].to == fa[u]) continue;
  69. t.push((Node){e[i].to});
  70. f[++cur] = e[i].to;
  71. }
  72. q.pop();
  73. }
  74. int num;
  75. if(!t.empty()) {
  76. int u = t.top().val; t.pop();
  77. if(!t.empty() && rand() % 233 == 0) {
  78. num = t.top().val; t.pop();
  79. } else num = u;
  80. }
  81. for(int i = 1; i <= cur; ++i) {
  82. if(f[i] == num) continue;
  83. q.push((Node){f[i]});
  84. }
  85. }
  86. return ans;
  87. }
  88. int main() {
  89. #ifndef ONLINE_JUDGE
  90. freopen("1.in", "r", stdin);
  91. #endif
  92. srand((unsigned)time(0));
  93. n = read(), m = read();
  94. for(int i = 1; i <= m; ++i) {
  95. int u = read(), v = read();
  96. ins(u, v); ins(v, u);
  97. }
  98. dfs(1);
  99. int ans = 1000000;
  100. for(int i = 1; i <= 200; ++i) {
  101. ans = min(ans, solve());
  102. }
  103. printf("%d\n", ans);
  104. }

过段时间补个搜索做法

LuoguP1041 传染病控制的更多相关文章

  1. luoguP1041 传染病控制 x

    P1041 传染病控制 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染 ...

  2. [luoguP1041] 传染病控制(DFS)

    传送门 n <= 300 结果裸的dfs就直接过了.. 枚举每一层,枚举删除每一层的边,然后把删除的边所连接的子树全部删去 代码 #include <vector> #include ...

  3. NOIP2003 传染病控制

    题四     传染病控制 [问题背景] 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国 大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完 全认 ...

  4. P1041 传染病控制(dfs)

    P1041 传染病控制 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染 ...

  5. [COGS 0107][NOIP 2003] 传染病控制

    107. [NOIP2003] 传染病控制 ★★★   输入文件:epidemic.in   输出文件:epidemic.out   简单对比时间限制:1 s   内存限制:128 MB [问题背景] ...

  6. AC日记——传染病控制 洛谷 P1041

    传染病控制 思路: 题目想问的是: 有一棵树: 对于除1外每个深度可以剪掉一棵子树: 问最后剩下多少节点: 题目意思一简单,这个题立马就变水了: 搜索就能ac: 数据有为链的情况,按深度为层次搜索的话 ...

  7. 【搜索】P1041 传染病控制

    题目链接:P1041 传染病控制 题解: 这个题目是看别人的博客做出来的,其实挺不错的一个题目,考察的东西挺多的, 一个dfs可以处理5个东西: 1.找出父亲 2.找出深度 3.每一层的节点,存进Ve ...

  8. Luogu P1041 [2003NOIP提高组]传染病控制

    P1041 传染病控制 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染 ...

  9. 洛谷 P1041 传染病控制

    P1041 传染病控制 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染 ...

随机推荐

  1. fzu2204 dp

    2015-10-06 19:31:05 n个有标号的球围成一个圈.每个球有两种颜色可以选择黑或白染色.问有多少种方案使得没有出现连续白球7个或连续黑球7个. 每组包含n,表示球的个数.(1 <= ...

  2. 关于poi导出excel方式HSSFWorkbook(xls).XSSFWorkbook(xlsx).SXSSFWorkbook.csv的总结

    1.HSSFWorkbook(xls) import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermo ...

  3. 【Linux学习七】软件安装

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 一.编译安装1.解压 源码文件是压缩包 要先解压tar -zxvf t ...

  4. 网易新网 spider

    # -*- coding: utf-8 -*- import os import sys import urllib.request import requests import re from lx ...

  5. jdk和jre区别

  6. 基于Kubernetess集群部署完整示例——Guestbook

    目录贴:Kubernetes学习系列 本文依赖环境:Centos7部署Kubernetes集群.基于Kubernetes集群部署skyDNS服务 该示例中,我们将创建一个redis-master.两个 ...

  7. flask模板应用-消息闪现(flash())

    消息闪现 flask提供了一个非常有用的flash()函数,它可以用来“闪现”需要提示给用户的消息,比如当用户登录成功后显示“欢迎回来!”.在视图函数调用flash()函数,传入消息内容,flash( ...

  8. vue生产环境清除console.log

    npm run build 后的生产环境的代码,会有很多开发时留下的console.log(),不可能每个页面不停地删除 在build/webpack.prod.conf.js文件里加上这样一段代码即 ...

  9. 如何在Linux中使用Firejail运行应用程序

    有时您可能希望使用在不同环境中未经过良好测试的应用程序,但您必须使用它们.在这种情况下,关注系统的安全性是正常的.在Linux中可以做的一件事是在沙箱中使用应用程序. “沙盒”是在有限环境中运行应用程 ...

  10. nginx实现MySQL负载均衡

    默认Nginx只支持http的反向代理,要想nginx支持tcp的反向代理,还需要在编译时增加tcp代理模块支持,即nginx_tcp_proxy_module 下面操作步骤只让nginx支持tcp_ ...