【刷题】【树上搜索】传染病控制
时间:2019-10-31
本文章向大家介绍【刷题】【树上搜索】传染病控制,主要包括【刷题】【树上搜索】传染病控制使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
一个比较奇怪的情况,每次砍掉一颗子树,其他会拓展,
求最小扩展数,
准备想dp,但是仔细看一下这个过程,
在某一阶段,我有dep_sz[nw]个点会继续扩展,其他的被砍了,
然后我挑一个点隔离,其他的还是继续扩展,
这里的哪个点怎么挑呢?
与子树节点和有关?贪心选择son_sz最大的点,会wa,因为还有一个g_sz变量
而且每次隔离这个点后,这个点的son_sz都没了,
但是受影响的是他的兄弟,
并且兄弟的情况会变得很复杂......
有下一层隔断的,下下层隔断的,时间各不相同
但是我们可以从上面的思路中,发现,
我们总共会隔离最多mx_dep次,
并且,第i次,隔离的必定为dep==i+1次(root的深度为1)
每次被隔离的其实不多,更多的是还在感染的,
这样dp其实反而效率不高,搜索更快
所以就以dep为阶段,搜索
注意标记的过程,这样最快,取消也最容易,但是前一种写法是错的
void dfs_0(int rt,int dp) { sz[rt]=1; dep[dp].push_back(rt),dep_sz[dp]++; g_sz[rt]=g[rt].size() ; for(int i=0;i<g_sz[rt];i++) if(g[rt][i]!=fa[rt]) { fa[g[rt][i]]=rt; dfs_0(g[rt][i],dp+1); sz[rt]+=sz[g[rt][i]]; } }
void dfs(int dp,int ans) { int res=dep_sz[dp]; for(int i=0;i<dep_sz[dp];i++) { int rt=dep[dp][i]; if(vis[fa[rt]]) { res--; vis[rt]=true; } else vis[rt]=false; } if(!res) min_ans=min(min_ans,ans); else for(int i=0;i<dep_sz[dp];i++) { int rt=dep[dp][i]; if(!vis[rt]) { vis[rt]=true; dfs(dp+1,ans-sz[rt]); vis[rt]=false; } } }
全部代码:
#include<cstdio> #include<cstdlib> #include<vector> using namespace std; int n,m; const int N=303; vector <int> g[N],dep[N]; int g_sz[N],dep_sz[N]; int sz[N],fa[N]; void dfs_0(int rt,int dp) { sz[rt]=1; dep[dp].push_back(rt),dep_sz[dp]++; g_sz[rt]=g[rt].size() ; for(int i=0;i<g_sz[rt];i++) if(g[rt][i]!=fa[rt]) { fa[g[rt][i]]=rt; dfs_0(g[rt][i],dp+1); sz[rt]+=sz[g[rt][i]]; } } int min_ans; bool vis[N]; void dfs(int dp,int ans) { int res=dep_sz[dp]; for(int i=0;i<dep_sz[dp];i++) { int rt=dep[dp][i]; if(vis[fa[rt]]) { res--; vis[rt]=true; } else vis[rt]=false; } if(!res) min_ans=min(min_ans,ans); else for(int i=0;i<dep_sz[dp];i++) { int rt=dep[dp][i]; if(!vis[rt]) { vis[rt]=true; dfs(dp+1,ans-sz[rt]); vis[rt]=false; } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); g[u].push_back(v),g[v].push_back(u); } dfs_0(1,1); min_ans=n-1; dfs(2,n); for(int i=2;i<=n;i++) if(!sz[i]) min_ans--; printf("%d\n",min_ans); return 0; }
原文地址:https://www.cnblogs.com/xwww666666/p/11771000.html
- Android查缺补漏(IPC篇)-- 进程间通讯之Socket简介及示例
- Android查缺补漏(IPC篇)-- Bundle、文件共享、ContentProvider、Messenger四种进程间通讯介绍
- Android查缺补漏(View篇)--布局文件中的“@+id”和“@id”有什么区别?
- Name node is in safe mode.
- Android查缺补漏(View篇)--事件分发机制源码分析
- Android查缺补漏(View篇)--事件分发机制
- Android查缺补漏(View篇)--自定义View利器Canvas和Paint详解
- Android查缺补漏(View篇)--自定义 View 的基本流程
- CVPR2018: Unsupervised Cross-dataset Person Re-identification by Transfer Learning of Spatio-tempora
- 一个数据包消灭一台服务器的DNS漏洞
- java文件基本操作与实例
- 如何在Azkaban中安装HDFS插件以及与CDH集成
- CVE-2017-5123 漏洞利用全攻略
- sqlmap被ban了ip怎么办
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Go 语言学习之运算符
- 神奇!如何快速成为一名优秀的YAML工程师?
- 移动端H5开发入门
- Go 语言学习之流程控制
- MinGW 安装
- 实践 | 目前最快精度最高检测框架(EfficientDet)
- 解决拉取github仓库报错“gnutls_handshake() failed”问题
- HTML 学习
- Go 语言学习之数组
- 坐姿不对,屏幕就变模糊!小姐姐教你用TensorFlow做一款“隐形背背佳”
- 七日Python之路--第九天(blog与Django)
- Python数据可视化-seaborn Iris鸢尾花数据
- pythonGUI -- pyside安装与初试
- TS 设计模式02 - 建造者模式
- 艺术鬼才!Unicode 字符还能这么玩?