CF1120 D. Power Tree 巧妙的图论转化

news/2024/7/15 17:31:11 标签: 图论, 算法, 深度优先

传送门

[前题提要]:无

题目描述:

就是给你一棵树,然后每个点有花费,然后你可以选一个点,付费后对这个点的子树的所有叶子结点增减任意权值.
考虑有一个人会给这棵树的所有叶子结点赋值(值我们不知道),输出最小的花费,使得无论它如何赋值,我们使用上述的花
费都能使所有的叶子节点变为0

考虑对一个点的子树的所有叶子节点进行增减任意值.不难联想到对一个点的子树的所有节点增减任意值的做法.所以考虑使用类似于树链剖分的方式将树上修改化为链上区间修改.
考虑记录一个点的所有叶子节点,并且按照 d f s dfs dfs序将其离散化存下.按照 d f s dfs dfs序的性质,我们会发现一个点的所有叶子节点必然是连续的区间.那么此时我们的问题就变成了:
给你 n n n个可以修改的区间,每一个区间都有其修改范围,修改每一个区间需要一定花费,问你至少需要多少花费将所有数字变为0
考虑到区间修改以及单点查询,我们想到使用差分来解决.假设我们使用一个差分数组 k [ i ] = a [ i ] − a [ i − 1 ] k[i]=a[i]-a[i-1] k[i]=a[i]a[i1],那么对于每一次区间修改来说,我们都是 a [ l ] + = v a l , a [ r + 1 ] − = v a l a[l]+=val,a[r+1]-=val a[l]+=val,a[r+1]=val,那么最终我们需要得到的所有的 k [ i ] = = 0 k[i]==0 k[i]==0.
此时有一个巧妙的转化,考虑我们需要所有的k[i]变为0,但是显然我们的差分数组是不改变前缀和的,所以此时所有的值肯定都转移到了cnt+1的位置(假设我们有cnt个叶子节点),那么对于我们的数的转移来说,我们只能将 l l l转移到 r + 1 r+1 r+1,如果我们将转移过程看成边,将每一个叶子结点看成点,那么我们想将所有的值都转移到 c n t + 1 cnt+1 cnt+1,就需要所有的点都联通才行,这样才能保证无论怎么赋值我们都可以将其转移到 c n t + 1 cnt+1 cnt+1的位置
那么此时这道题就简单了,考虑到必须所有点都联通,每次选择联通一个点我们都需要花费,又需要花费最小,所以显然是个最小生成树的模型,此时使用最小生成树跑一下就行.

但是还有一个问题,那就是这道题的最终问题是所有的可能性的最小生成树的点,所以我们用朴素的 k r u s k a l kruskal kruskal跑出来的只是一棵树,需要改一下.考虑到最小生成树的性质,当边相同时,我们可以选择任意一条不在联通块中的边,所以这些边显然都是平等的,所以这些边都是我们的答案(当然这一点是可以严谨证明的,但是限于篇幅,此处不再赘述)


下面是具体的代码部分:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
	ll x=0,w=1;char ch=getchar();
	for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x*w;
}
inline void print(__int128 x){
	if(x<0) {putchar('-');x=-x;}
	if(x>9) print(x/10);
	putchar(x%10+'0');
}
#define maxn 1000000
#define int long long
const double eps=1e-8;
#define	int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
int w[maxn];vector<int>edge[maxn];int l[maxn],r[maxn];
int cnt=0;
void dfs(int u,int per_u) {
	if(edge[u].size()==1&&u!=1) {
		++cnt;l[u]=r[u]=cnt;
	}
	for(auto v:edge[u]) {
		if(v==per_u) continue;
		dfs(v,u);
		l[u]=min(l[u],l[v]);
		r[u]=max(r[u],r[v]);
	}
}
struct Edge{
	int u,v,w,id;
	bool operator < (const Edge &rhs) const {
		return w<rhs.w;
	}
}edge2[maxn];
int fa[maxn];
int find(int x) {
	if(x==fa[x]) return x;
	else return fa[x]=find(fa[x]);
}
signed main() {
	int n=read();
	for(int i=1;i<=n;i++) {
		w[i]=read();
	}
	for(int i=1;i<n;i++) {
		int u=read();int v=read();
		edge[u].push_back(v);
		edge[v].push_back(u);
	}
	memset(l,0x3f,sizeof l);
	memset(r,-0x3f,sizeof r);
	dfs(1,0);
	for(int i=1;i<=n;i++) {
		int u=l[i],v=r[i];
		edge2[i]={u,v+1,w[i],i};
	}
	for(int i=1;i<=cnt;i++) fa[i]=i;
	sort(edge2+1,edge2+1+n);
	vector<int>ans;int this_cnt=0;int need=0;
	for(int i=1;i<=n;i++) {
		int r=i;
		while(r+1<=n&&edge2[r+1].w==edge2[r].w) r++;
		for(int j=i;j<=r;j++) {
			auto [u,v,w,k]=edge2[j];
			if(find(u)!=find(v)) {
				this_cnt++;ans.push_back(k);
			}
		}
		for(int j=i;j<=r;j++) {
			auto [u,v,w,k]=edge2[j];
			if(find(u)!=find(v)) {
				need+=w;
				fa[find(u)]=find(v);
			}
		}
		i=r;
	}
	sort(ans.begin(),ans.end());
	cout<<need<<" "<<ans.size()<<endl;
	for(auto i:ans) cout<<i<<" ";
	return 0;
}

http://www.niftyadmin.cn/n/4998898.html

相关文章

海底光缆走线逻辑

Submarine Cable Map 电信公司Telegeography每年都会发布其海底电缆地图的新版本。这张地图显示了在世界各地传输数据的所有海底电信电缆。2023 年海底电缆地图现已推出。

【Java核心知识】泛型和类型擦除

文章目录 泛型什么是泛型类型限定类型擦除如何在运行时判断泛型具体类型参考链接 泛型 什么是泛型 Java中的泛型是通过定义模板参数来处理一类操作&#xff0c;这类操作并不关心具体传入的参数类型。比如对于add()方法来说&#xff0c;我们可以使两个int相加&#xff0c;也可…

Nginx笔记-vue项目刷新出现404(try_files和index)

目前的nginx.conf配置&#xff1a; ......server{............location /xxx{root /home/userName/dirindex index.html}} 部署是成功了&#xff0c;但是有个问题&#xff0c;就是感觉整个前端不会找uri&#xff0c;按F5或者在浏览器输入url都会404&#xff0c;只从vue默认的…

(10)(10.8) 固件下载

文章目录 ​​​​​​​前言 10.8.1 固件 10.8.2 Bootloader 10.8.3 APM2.x Autopilot 10.8.4 许可证 10.8.5 安全 前言 固件服务器(firmware server)可提供所有飞行器的最新固件。其中包括&#xff1a; CopterPlaneRoverAntennaTrackerSub 本页提供了一些被视为&quo…

9.3.tensorRT高级(4)封装系列-自动驾驶案例项目self-driving-车道线检测

目录 前言1. 车道线检测总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-自动驾驶案例项目self-driving-车道…

【大模型】自动化问答生成:使用GPT-3.5将文档转化为问答对

自动化问答生成&#xff1a;使用GPT-3.5将文档转化为问答对 正文步骤1&#xff1a;准备工作步骤2&#xff1a;编写Python脚本 总结 当我们需要将大段文档转化为问答对时&#xff0c;OpenAI的GPT-3.5模型提供了一个强大的工具。这个教程将向您展示如何编写一个Python脚本&#x…

nginx中模块的设置以及反向代理

nginx设置 nginx http 模块的配置文件位于 "/apps/nginx/conf/nginx.conf"&#xff08;以自己安装时选择的目录为准&#xff0c;若使用yum安装&#xff0c;则在 /etc/nginx/nginx.conf&#xff09;。在该文件中&#xff0c;需要定义一些常见的配置项&#xff0c;包括…

Web安全——穷举爆破下篇(仅供学习)

Web安全 一、常见的端口服务穷举1、hydra 密码穷举工具的使用2、使用 hydra 穷举 ssh 服务3、使用 hydra 穷举 ftp 服务4、使用 hydra 穷举 mysql 服务5、使用 hydra 穷举 smb 服务6、使用 hydra 穷举 http 服务7、使用 hydra 穷举 pop3 服务8、使用 hydra 穷举 rdp 服务9、使用…