NOIP2012 疫情控制[通俗易懂]

NOIP2012 疫情控制[通俗易懂]也许更好的阅读体验Description\mathcal{Description}Description原题链接一句话题意一个人可以堵住一个子树,不能一次堵住整棵树,求堵住每个通往叶子节点的路径,走的最远的那个人走的路程最少是多少,若不能堵住输出−1-1−1Solution\mathcal{Solution}Solution看了下其他题解,都说很毒瘤最开始我也认为很毒瘤就是在决…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

也许更好的阅读体验

D e s c r i p t i o n \mathcal{Description} Description
原题链接

set
一句话题意
一个人可以堵住一个子树,不能一次堵住整棵树,求堵住每个通往叶子节点的路径,走的最远的那个人走的路程最少是多少,若不能堵住输出 − 1 -1 1
data
S o l u t i o n \mathcal{Solution} Solution
看了下其他题解,都说很毒瘤
最开始我也认为很毒瘤
就是在决定一个点是否要跨过根这个地方比较麻烦
但是在码的途中,突然想到一个无脑的方法
于是写起来就很愉快了

最…最…,显然二分路程是多少

再继续想之前,先看一下我们 c h e c k check check函数要求在什么复杂度决定
n ≤ 50000 n\leq 50000 n50000,可以 n l o g 2 n nlog^2n nlog2n解决,也就是说 c h e c k check check的复杂度只要小于 n l o g n nlogn nlogn即可

一个人在二分到的路程内,尽量往上走是最优的
若一个人可以到达根节点,那么就要考虑其跨过这个根节点去堵其它子树
显然,若跨过根节点,那么走到根节点下面的那个节点就可以了

对于一个可以跨过根节点的人,他可能不要跨过根节点,也可能要跨过根节点
也可能一个子树里的人跨过根节点去堵其他子树,另外的一个子树的人跨过根节点来堵他的子树,这是因为原来这个子树的人比较靠近根节点,跨过根节点后走的较远,而他所在子树与根节点的路径又比较短
想想好像有点麻烦,想到这顿时觉得这题很毒瘤

但其实,我们不用想那么多
我们把所有能跨过根节点的人都走到根节点
将其还允许走的路程全部记下来
把所有需要人去堵的子树找出来,记下其与根节点的距离
显然,能走得最远的人去堵距离根节点最远的子树是最优的

也就是说要从大到小排序,这个过程我们用一个大根堆维护即可
对于一个到子树的距离,我们记下其子树的编号,对于每棵子树,我们记下其内可以跨过根节点的人中,还允许走的路程最少的路程是多少

再考虑一个人可能不要跨过根节点,我们在弹大根堆时,若发现这棵子树可以用比当前允许走的路程最大的人更小的人替代,那么那个人就不需要跨过根节点了
由于那个人仍然在大根堆内,我们把其记在一个队列里,表示有哪些路程被提前用了
这样就是最优的
仍有不懂请看代码,我觉得还是很无脑的,毕竟什么特殊的操作都没有,代码应该一下就看懂了

C o d e \mathcal{Code} Code

/******************************* Author:Morning_Glory LANG:C++ Created Time:2019年10月22日 星期二 20时50分59秒 *******************************/
#include <cstdio>
#include <fstream>
#include <queue>
#define ll long long
#define inf 12345678987654
#define mp make_pair
using namespace std;
const int maxn = 500005;
const int maxm = 1000006;
const int lim = 20;
//{ 
   { 
   {cin
struct IO{ 
   
	template<typename T>
	IO & operator>>(T&res){ 
   
		res=0;
		bool flag=false;
		char ch;
		while((ch=getchar())>'9'||ch<'0')	flag|=ch=='-';
		while(ch>='0'&&ch<='9')	res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
		if (flag)	res=~res+1;
		return *this;
	}
}cin;
//}}}
int n,m,cnt,u,v,val,num;
int head[maxn],nxt[maxm],to[maxm],w[maxm],hav[maxn],dep[maxn],lg[maxn]={ 
   -1};
int fa[maxn][lim];
ll l,r,mid;
ll d[maxn],f[maxn];
bool vis[maxn];
priority_queue <int> qc,qf;
priority_queue < pair<int,int> >qn;
//{ 
   { 
   {add
void add (int u,int v,int val)
{ 
   
	nxt[++cnt]=head[u],head[u]=cnt,to[cnt]=v,w[cnt]=val;
}
//}}}
//{ 
   { 
   {dis
ll dis (int x,int y)
{ 
   
	return d[x]>d[y]?d[x]-d[y]:d[y]-d[x];
}
//}}}
//{ 
   { 
   {dfs
void dfs (int x)
{ 
   
	r=max(r,d[x]);
	for (int i=1;i<=lg[dep[x]];++i)	fa[x][i]=fa[fa[x][i-1]][i-1];

	for (int e=head[x];e;e=nxt[e])
		if (to[e]!=fa[x][0]){ 
   
			fa[to[e]][0]=x,dep[to[e]]=dep[x]+1;
			d[to[e]]=d[x]+w[e];
			dfs(to[e]);
		}
}
//}}}
//{ 
   { 
   {move
void move (int x,int nm)
{ 
   
	ll t=mid;
	for (int i=lg[dep[x]];~i;--i){ 
   
		ll ds=dis(fa[x][i],x);
		if (fa[x][i]>1&&t>=ds)	t-=ds,x=fa[x][i];
	}
	if (t>dis(1,x)){ 
   
		ll ds=t-dis(1,x);
		f[x]=min(f[x],ds);
		while (nm--)	qc.push(ds);
	}
	else	vis[x]=true;
}
//}}}
//{ 
   { 
   {chk
bool chk (int x)
{ 
   
	if (vis[x])	return	false;
	bool flag=true;
	for (int e=head[x];e;e=nxt[e])
		if (to[e]!=fa[x][0]){ 
   
			flag=false;
			if (chk(to[e]))	return true;
		}
	return flag;
}
//}}}
//{ 
   { 
   {check
bool check ()
{ 
   
	while (!qc.empty())	qc.pop();
	while (!qn.empty())	qn.pop();
	while (!qf.empty())	qf.pop();
	for (int i=1;i<=n;++i)	vis[i]=0,f[i]=inf;
	for (int i=1;i<=n;++i)
		if (hav[i])	move(i,hav[i]);

	for (int e=head[1];e;e=nxt[e])
		if (chk(to[e]))	qn.push(mp(w[e],to[e]));

	while (!qn.empty()){ 
   
		val=qn.top().first,v=qn.top().second,qn.pop();
		while (!qf.empty()&&qf.top()==qc.top())	qf.pop(),qc.pop();

		if (qc.empty())	return false;
		if (qc.top()<val){ 
   
			if (f[v]>qc.top())	return false;
			qf.push(f[v]);
		}
		else if (f[v]<=qc.top())	qf.push(f[v]);
		else	qc.pop();
	}
	return true;
}
//}}}
int main()
{ 
   
	cin>>n;
	for (int i=1;i<=n;++i)	lg[i]=lg[i>>1]+1;
	for (int i=2;i<=n;++i){ 
   
		cin>>u>>v>>val;
		if (u==1||v==1)	++num;
		add(u,v,val),add(v,u,val);
	}
	cin>>m;
	if (m<num)	return printf("-1\n"),0;
	for (int i=1;i<=m;++i) cin>>u,++hav[u];

	dfs(1);

	r<<=1;
	while (l<r){ 
   
		mid=(l+r)/2;
		if (check())	r=mid;
		else	l=mid+1;
	}

	printf("%lld\n",l);
	return 0;
}

如有哪里讲得不是很明白或是有错误,欢迎指正

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/172068.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 分子模拟软件amber_分子模拟软件Discovery Studio教程(十):构建基于受体-配体复合物药效团模型…

    分子模拟软件amber_分子模拟软件Discovery Studio教程(十):构建基于受体-配体复合物药效团模型…DiscoveryStudio™(简称DS)是专业的生命科学分子模拟软件,DS目前的主要功能包括:蛋白质的表征(包括蛋白-蛋白相互作用)、同源建模、分子力学计算和分子动力学模拟、基于结构药物设计工具(包括配体-蛋白质相互作用、全新药物设计和分子对接)、基于小分子的药物设计工具(包括定量构效关系、药效团、数据库筛选、ADMET)和组合库的设计与分析等。本章节利刃君为大家带来了使用Discover…

    2022年5月26日
    40
  • C语言 编写“剪刀石头布”小游戏[通俗易懂]

    C语言 编写“剪刀石头布”小游戏[通俗易懂]目录前言一、游戏原理二、C语言代码1.引入函数2.初始页面显示3.游戏过程及结果总结前言大家好~我是一名C语言初学者,学了C语言基础后,我制作了一个小游戏:剪刀石头布。希望大家能对我的思路和代码提出小Tips(eg.更简便的方法与程序)我也会虚心接受大家的建议~一、游戏原理“剪刀石头布”这个游戏,想必大家都很熟悉了。两个人在玩游戏时,事先都不知道对方将要出什么,这中间存在着一种随机性。而这种随机性相当于C语言里stdlib.h库中rand()函数,rand()函数用来产生随机数,因为r..

    2022年7月24日
    14
  • Python里divmod_python基本函数

    Python里divmod_python基本函数前言我们都知道,python中//代表整数运算中的取整,%代表整数运算中的取余,那么有什么函数可以同时取到整数和余数吗?答案是有的,使用python内置函数divmoddivmod首先看一下源

    2022年7月30日
    9
  • 腾讯早期投资人_腾讯大涨

    腾讯早期投资人_腾讯大涨腾讯“炒基”帝国崛起?作者l大钊排版l勤燐电影《华尔街》里有句经典台词叫,“资本永不眠”。那资本如何不眠呢,无非就是“以钱生钱”,经济基础决定上层建筑,靠庞大的金融帝国撑起更大的商业梦想。近日,深圳证监局发布关于核准腾安基金销售(深圳)有限公司证券投资基金销售业务资格的批复。而腾讯集团相关负责人在接受《国际金融报》记者采访时表示,腾安基金销售(深圳)有限公司是腾讯全资控股的独立基金销售机构,以腾讯理财通平台为基础,开展基金销售业务。拿下第三方基金销售牌照后,腾讯在金融领域就已完成了第三

    2022年9月23日
    4
  • SDRAM控制器设计(8)SDRAM控制器仿真验证

    SDRAM控制器设计(8)SDRAM控制器仿真验证到此,简单的可进行读写操作的SDRAM控制器模块就设计好了。接下来,结合仿真模型(镁光官网提供的SDRAM模型)sdr文件,和编写的testbench文件验证所设计的控制器是否正确。testbench如下`timescale1ns/1ns`defineCLK100_PERIOD10modulesdram_control_tb;`include”../src/Sdr…

    2022年7月25日
    14
  • WebSocket介绍和Socket的区别

    WebSocket介绍和Socket的区别  WebSocket介绍与原理WebSocketprotocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手需要借助HTTP请求完成。——百度百科目的:即时通讯,替代轮询网站上的即时通讯是很常见的,比如网页的QQ,聊天系统等。按照以往的技术能力通常是采用轮询、Comet技术解决。HTTP协议是非持久化的,单向的网…

    2022年7月11日
    16

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号