首页 > 其他分享 >P1084疫情控制 题解

P1084疫情控制 题解

时间:2023-10-14 16:22:45浏览次数:38  
标签:疫情 idx int 题解 tot ++ P1084 节点

P1084疫情控制

前言:这题思路不难,实现稍微有点难。总体来说,不算特别难的那种紫题,建议评蓝

题目描述

给定一些点,用这些点来切断根节点到所有叶子节点的路径,可以移动这些点,不同的点可以同时移动,求时间最少。

思考过程

  1. 不同的点可以同时移动:看到这里,我们可以转化一下题目:

    给定一些点,用这些点来切断根节点到所有叶子节点的路径,可以 移动这些点,求移动时间最长的点移动时间的最小值

    然后我们就想到二分答案。

  2. 二分的check(贪心)

    我们可以知道一个节点的子树所包含的叶子节点数一定大于等于这个节点的子节点的子树所包含的叶子节点数。所以我们希望检查点所在的节点深度越小越好。那么,我们可以先让一些在时间范围之内跳不到根节点的军队调到他能跳到最浅的节点建立检查点,其他军队调到根节点的子节点进行储备。然后,我们找到所有仍然可以被感染的节点。在找出所有没有建立检查点的军队,将他们匹配。判断是否成功就成功的二分啦。

  3. 倍增 :一个一个跳太慢,\(2^{i}\),\(2^{i-1}\)....2,1 的跳才快。

代码(不用注释了吧

/*
	Problem:P1084
	Author:lougu#756336
	Oneline Judge:luogu
	Solution:树上倍增+二分+贪心
	warning:no
*/
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e4+10,M=1e5+10,log_N=20;
int n,m;
int l,r,ans,flag,t_tot,d_tot,a_tot;
int a[N],dis[N][log_N],f[N][log_N];
int head[N],nxt[M],to[M],w[M],idx;
bool vis[N],need[N];
int ti[N],di[N];
pair<int,int> ar[N];
void add(int x,int y,int z){to[++idx]=y,w[idx]=z,nxt[idx]=head[x],head[x]=idx;}
void dfs_bz(int x,int fa,int dist)
{
	f[x][0]=fa,dis[x][0]=dist;
	for(int i=1;i<log_N;i++)
	{
		f[x][i]=f[f[x][i-1]][i-1];
		dis[x][i]=dis[x][i-1]+dis[f[x][i-1]][i-1];
	}
	for(int i=head[x];i;i=nxt[i])
	{
		if(to[i]==fa)continue;
		dfs_bz(to[i],x,w[i]);
	}
}
bool dfs(int x,int fa)
{
	bool fl=0;
	if(vis[x])return 0;
	for(int i=head[x];i;i=nxt[i])
	{
		if(to[i]==fa)continue;
		fl=1;
		if(dfs(to[i],x))return 1;
	}
	if(!fl)return 1;
	return 0;
}
bool check(int lim)
{
	memset(vis,0,sizeof vis);
	memset(ti,0,sizeof ti);
	memset(di,0,sizeof di);
	memset(ar,0,sizeof ar);
	memset(need,0,sizeof need);
	t_tot=d_tot=a_tot=0;
	for(int i=1;i<=m;i++)
	{
		int x=a[i],cnt=0;
		for(int j=log_N-1;j>=0;j--)
			if(f[x][j]>1&&cnt+dis[x][j]<=lim)
				cnt+=dis[x][j],x=f[x][j];
		if(f[x][0]==1&&cnt+dis[x][0]<=lim)
			ar[++a_tot]=make_pair(lim-cnt-dis[x][0],x);
		else vis[x]=1;
	}
	for(int i=head[1];i;i=nxt[i])need[to[i]]=dfs(to[i],1);
	sort(ar+1,ar+a_tot+1);
	for(int i=1;i<=a_tot;i++)
		if(need[ar[i].second]&&ar[i].first<dis[ar[i].second][0])
			need[ar[i].second]=0;
		else ti[++t_tot]=ar[i].first;
	for(int i=head[1];i;i=nxt[i])
		if(need[to[i]])di[++d_tot]=dis[to[i]][0];
	if(t_tot<d_tot)return 0; 
	sort(ti+1,ti+t_tot+1),sort(di+1,di+d_tot+1);
	int i=1,j=1;
	while(i<=d_tot&&j<=a_tot)
		if(ti[j]>=di[i])i++,j++;
		else j++;
	if(i>d_tot)return 1;
	return 0;
}
signed main()
{
	scanf("%lld",&n);
	for(int i=1,x,y,z;i<n;i++)
	{
		scanf("%lld%lld%lld",&x,&y,&z);
		add(x,y,z),add(y,x,z);
		r+=z;
	}
	dfs_bz(1,0,0);
	scanf("%lld",&m);
	for(int i=1;i<=m;i++)
		scanf("%lld",&a[i]);
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(check(mid))r=mid-1,ans=mid,flag=1;
		else l=mid+1;
	}
	if(!flag)printf("-1");
	else printf("%lld",ans);
	return 0;
}

标签:疫情,idx,int,题解,tot,++,P1084,节点
From: https://www.cnblogs.com/gdfzlcx/p/17764313.html

相关文章

  • [AGC033C] Removing Coins题解
    思路可以看出,每次对一个点\(u\)操作一次,就相当于删除以\(u\)为根的所有叶节点。当然我们还是没有什么思路,我们可以想简单一点:在一条链上的情况。如果\(u\)是链的端点:以\(u\)为根节点的叶节点只有一个,所以链的长度减一。如果\(u\)不是链的端点:以\(u\)为根节点......
  • P1612 [yLOI2018] 树上的链 题解
    思路看到条件\(2\),我们得知:这个节点对应的最长链,一定在这个节点到根节点的简单路径上。所以我们记录\(1\)到\(i\)之间的权值和,记为\(sum_i\)。因为权值是正整数,所以满足单调性,可以二分。如何二分路径上的点呢?我们维护一个与当前dfs同步的栈,记录从根节点到当前节点的简......
  • [ARC116C] Multiple Sequences题解
    思路我们可以很好的想到一种\(O(nm)\)的dp:状态:\(dp_{i,j}\)为搜到第\(i\)个,最后一个数是\(j\)的方案数。转移:\(dp_{i,j}=\displaystyle\sum_{k|j,k\not=j}dp_{i-1,k}\)当然这是会超时的。我们换一种思路,我们先枚举最后一个数,再计算方案数。这有个好处,我们缩小......
  • 苏格拉底问答、实践过程截图、遇到问题解决问题截图,代码链接
    defineVOLUME_NAME"EXT2FS"//卷名#defineBLOCK_SIZE512//块大小#defineDISK_SIZE4612//磁盘总块数defineDISK_START0//磁盘开始地址#defineSB_SIZE32//超级块大小是32BdefineGD_SIZE32//块组描述符大小是32B#defineGDT_START(0+512)//块组描述......
  • Android项目在 app 中通过 WebView 访问 url显示空白,使用浏览器可以打开,Android WebVi
    这是服务器证书校验WebView的安全问题服务器证书校验主要针对WebView的安全问题。在app中需要通过WebView访问url,因为服务器采用的自签名证书,而不是ca认证,使用WebView加载url的时候会显示为空白,出现无法加载网页的情况。使用ca认证的证书,在WebView则可以直接......
  • 网络规划设计师真题解析--PERT “计划评审技术”(三点估算法)
    某网络建设项目的安装阶段分为A、B、C、D四个活动任务,各任务顺次进行,无时间上重叠,各任务完成时间估计如下图所示,按照计划评审技术,安装阶段工期估算为(70)天。(2019年)(70)A.31   B.51    C.53    D.83答案:C解析:依据三点估算公示,活动历时均值=(最悲观时间+最可能时间*4+......
  • 算法题解——多数元素
    题目给定一个大小为n的数组nums,返回其中的多数元素。多数元素是指在数组中出现次数大于⌊n/2⌋的元素。你可以假设数组是非空的,并且给定的数组总是存在多数元素。示例1:输入:nums=[3,2,3]输出:3示例2:输入:nums=[2,2,1,1,1,2,2]输出:2提示:n==nums.length......
  • [AGC009B] Tournament 题解
    思路考虑树形\(\text{dp}\)。我们将每个人与把自己淘汰的人连边。得到一颗以一为根的树。由于我们需要求出必须赢的场数最多的那位选手,至少要赢多少场。考虑最多的限制。可以使用树型动态规划。每一次两个人比赛的代价为:\[dp_i=\max(dp_i,dp_j)+1\]这样就达成了最多的限......
  • 题解:CF118E
    Tarjan思路先来看一下题目给出的无解的这个样例。不难发现,导致无解的两条边就是\(6-7\)和\(2-4\)这两个桥。所以这个题就转换成了求桥,如果存在桥就是无解。代码#include<bits/stdc++.h>usingnamespacestd;constintN=1e5+5,M=3e5+5;inlineintread();intn,......
  • [AGC037D] Sorting a Grid 题解
    学长给我看了这道题,感觉很有趣啊!想了想想出来了。考虑先把每个数还原到对应行上,然后用最后一次把它们斗出来。那么我们就是要在第一次操作后,对于每种颜色使得它平铺在这个块上。那么我们直接网络流或二分图匹配构造一下方案就做完力!......