LuoguP1041 传染病控制
题目地址
题解
这里讲一个非正解——贪心+随机化。
贪心的想法是什么?
我们dfs一遍处理出每个节点子树内的节点数量,记为\(siz\)。
贪心的砍掉\(siz\)最大的那个子树,在树的形态比较正常的情况下是可以得到最优解的。
如何hack掉这种贪心?
构造一条链,在中间的地方放一个“很胖”的分支,可以只分两层,每层的节点构造多一些(注意要使这个分支的节点数量小于链下半部分的节点数量)
这样子我们按照上述贪心,将会得到错误的结果,更优的做法是把这个分支直接砍掉(因为链上每次传染只会增加一个被传染的人)
当然,实际构造可以更加复杂,这只是最极端的情况。
不过,这种错误的贪心已经可以得到90分了。
如何得到满分?
要对答案产生影响,那么需要的那个分支的大小就不会太小(因为实际情况下一般是不会像上面那样子构造的,毒瘤出题人除外)
我们采用随机化的思想(实际上下面这个随机化的方法并不好,不过数据水也就水过去了)。
我们定义一种判定规则,如果某个节点恰好符合这个判定规则(一般是随机的),那么就改变原本的贪心策略,换用另外一个策略。
这里用的判定规则是rand出来的结果对233取模是否为0.
如果符合这个判定规则的话,我们就选择子树大小第二大(这个使用优先队列实现)的子树砍掉。
当然,这很不靠谱。
通常的做法是在不TLE的情况下尽量跑多次(能多少次就多少次),对所有结果取min。
所以随机化能水过去一般靠大量的尝试,尽量靠谱的判定规则,以及另外一个策略靠不靠谱。。。
注意,在此题中,需要使判定成功的可能性尽可能低,当然也不能太低
下面给出代码,注意,因为代码里只跑了200次进行尝试,不保证一定能ac,可以自行调大次数,或者多交几次(我交了2发才过)。
#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define il inline
namespace io {
#define in(a) a=read()
#define out(a) write(a)
#define outn(a) out(a),putchar('\n')
#define I_int ll
inline I_int read() {
I_int x = 0 , f = 1 ; char c = getchar() ;
while( c < '0' || c > '9' ) { if( c == '-' ) f = -1 ; c = getchar() ; }
while( c >= '0' && c <= '9' ) { x = x * 10 + c - '0' ; c = getchar() ; }
return x * f ;
}
char F[ 200 ] ;
inline void write( I_int x ) {
if( x == 0 ) { putchar( '0' ) ; return ; }
I_int tmp = x > 0 ? x : -x ;
if( x < 0 ) putchar( '-' ) ;
int cnt = 0 ;
while( tmp > 0 ) {
F[ cnt ++ ] = tmp % 10 + '0' ;
tmp /= 10 ;
}
while( cnt > 0 ) putchar( F[ -- cnt ] ) ;
}
#undef I_int
}
using namespace io ;
using namespace std ;
#define N 310
int n, m, f[N];
int cnt, head[N], siz[N], fa[N];
struct edge {
int to, nxt;
}e[N<<1];
void ins(int u, int v) {
e[++cnt] = (edge) {v, head[u]};
head[u] = cnt;
}
void dfs(int u) {
siz[u] = 1;
for(int i = head[u]; i; i = e[i].nxt) {
if(e[i].to == fa[u]) continue;
fa[e[i].to] = u;
dfs(e[i].to);
siz[u] += siz[e[i].to];
}
}
struct Node {
int val;
};
priority_queue<Node> q, t;
bool operator < (Node a, Node b) {
return siz[a.val] < siz[b.val];
}
int solve() {
while(!q.empty()) q.pop();
int ans = 0;
q.push((Node){1});
while(!q.empty()) {
int cur = 0;
while(!t.empty()) t.pop();
while(!q.empty()) {
int u = q.top().val; ++ans;
for(int i = head[u]; i; i = e[i].nxt) {
if(e[i].to == fa[u]) continue;
t.push((Node){e[i].to});
f[++cur] = e[i].to;
}
q.pop();
}
int num;
if(!t.empty()) {
int u = t.top().val; t.pop();
if(!t.empty() && rand() % 233 == 0) {
num = t.top().val; t.pop();
} else num = u;
}
for(int i = 1; i <= cur; ++i) {
if(f[i] == num) continue;
q.push((Node){f[i]});
}
}
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("1.in", "r", stdin);
#endif
srand((unsigned)time(0));
n = read(), m = read();
for(int i = 1; i <= m; ++i) {
int u = read(), v = read();
ins(u, v); ins(v, u);
}
dfs(1);
int ans = 1000000;
for(int i = 1; i <= 200; ++i) {
ans = min(ans, solve());
}
printf("%d\n", ans);
}
过段时间补个搜索做法
LuoguP1041 传染病控制的更多相关文章
- luoguP1041 传染病控制 x
P1041 传染病控制 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染 ...
- [luoguP1041] 传染病控制(DFS)
传送门 n <= 300 结果裸的dfs就直接过了.. 枚举每一层,枚举删除每一层的边,然后把删除的边所连接的子树全部删去 代码 #include <vector> #include ...
- NOIP2003 传染病控制
题四 传染病控制 [问题背景] 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国 大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完 全认 ...
- P1041 传染病控制(dfs)
P1041 传染病控制 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染 ...
- [COGS 0107][NOIP 2003] 传染病控制
107. [NOIP2003] 传染病控制 ★★★ 输入文件:epidemic.in 输出文件:epidemic.out 简单对比时间限制:1 s 内存限制:128 MB [问题背景] ...
- AC日记——传染病控制 洛谷 P1041
传染病控制 思路: 题目想问的是: 有一棵树: 对于除1外每个深度可以剪掉一棵子树: 问最后剩下多少节点: 题目意思一简单,这个题立马就变水了: 搜索就能ac: 数据有为链的情况,按深度为层次搜索的话 ...
- 【搜索】P1041 传染病控制
题目链接:P1041 传染病控制 题解: 这个题目是看别人的博客做出来的,其实挺不错的一个题目,考察的东西挺多的, 一个dfs可以处理5个东西: 1.找出父亲 2.找出深度 3.每一层的节点,存进Ve ...
- Luogu P1041 [2003NOIP提高组]传染病控制
P1041 传染病控制 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染 ...
- 洛谷 P1041 传染病控制
P1041 传染病控制 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染 ...
随机推荐
- Python全栈-day1-day2-计算机基础
计算机基础 1.编程语言 语言即事物之间沟通的介质,编程语言即程序员与计算机沟通的介质.程序员通过编写计算机程序使得计算机能够按照人预先的期望执行相应的动作,从而达到在某种程度上解放人和实现人类难以实 ...
- hdu2609最小表示法
#include <iostream> #include <algorithm> #include <string.h> #include <cstdio&g ...
- Python -- Pandas介绍及简单实用【转】
转http://www.datadependence.com/2016/05/scientific-python-pandas/ 一. Pandas简介 1.Python Data Analysis ...
- 20165215 2017-2018-2 《Java程序设计》第6周学习总结
20165215 2017-2018-2 <Java程序设计>第6周学习总结 教材学习内容总结 chapter8 Java把String类定义为final类,即String类不能有子类 用 ...
- QXDM操作应用
QXDM(The QUALCOMM Extensible Diagnostic Monitor)是高通公司(Qualcomm)公司发布的可以对手机终端所发数据进行跟踪有效工具,通过对数据的分析可以诊断 ...
- jsky使用小记
jsky是一款深度WEB应用安全评估工具,能轻松应对各种复杂的WEB应用,全面深入发现里面存在的安全弱点. jsky可以检测出包括SQL注入.跨站脚本.目录泄露.网页木马等在内的所有的WEB应用层漏洞 ...
- javaweb笔记—04(预编译和泛型)
预编译:ps对象1.ps可进行预编译,占位符传值,性能高于sta的(数据库驱动层有优化)2.比较灵活,数据库将预编译的SQL缓存了,第二次访问,就不用预编译,直接执行.3.较为安全,不会发生SQL注入 ...
- MyEclipse配置默认自带的Java代码格式化
1.配置注释一大段代码块后,格式化代码,已经注释的代码仍然保持原样 (1)首先,Window -> Prefrences -> Java -> Code Style -> Fo ...
- xml文件中[Invalid byte 1 of 1-byte UTF-8 sequence.]的解决方案
问题描述: 导入项目包后发生xml文件出现错误信息:[Invalid byte 1 of 1-byte UTF-8 sequence.],如下截图所示: 解决方案: 将xml文件全部内容剪切到Note ...
- everything不显示移动硬盘中路径
点击他的设置选项,里面有NTFS,移除那些硬盘就可以了.