首页 > 其他分享 >2024.04.11 树上问题回顾

2024.04.11 树上问题回顾

时间:2024-04-11 21:57:21浏览次数:23  
标签:11 2024.04 ch 回顾 int de read maxn getchar

2024.04.11 树上问题回顾

P2015 二叉苹果树

树形背包板子题。

需要注意的是,枚举儿子 \(v\) 的选择数量 \(k\) 时,一定要先转移 \(k=0\) 的情况,否则就会用新状态来重复更新新状态,违背 \(0/1\) 背包的思路。

#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline T read(){
    T x=0;char ch=getchar();bool fl=false;
    while(!isdigit(ch)){if(ch=='-')fl=true;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return fl?-x:x;
}
#define read() read<int>()
#define LL long long
const int maxn = 100 + 5;
int head[maxn],cnt;
struct edge{
	int to,nxt,w;
}e[maxn<<1];
inline void link(int u,int v,int w){
	e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;e[cnt].w=w;
}
int n,q,f[maxn][maxn],sz[maxn];
void dfs(int u,int fa){
	f[u][0]=0;sz[u]=1;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==fa)continue;
		dfs(v,u);
		sz[u]+=sz[v];
		for(int j=min(sz[u]-1,q);j>=0;j--){
			for(int k=0;k<=min(sz[v]-1,j);k++){
				f[u][j]=max(f[u][j],f[u][j-k]+f[v][k]+e[i].w);
				if(k<j)f[u][j]=max(f[u][j],f[u][j-k-1]);
			}
		}
	}
}
int main(){
	n=read();q=read();
	q=(n-1)-q;
	for(int i=1;i<n;i++){
		int u=read(),v=read(),w=read();
		link(u,v,w);link(v,u,w);
	}
	memset(f,0xcf,sizeof f);
	dfs(1,0);
	cout<<f[1][q]<<endl;
	return 0;
}

P4281 [AHOI2008]紧急集合/聚会

树上有三个点 \(x,y,z\),选择一个点 \(u\) 使得三个点到 \(u\) 的距离和最短。

显然最短路径中,每条树边最多经过一次。

手玩一下发现,\(u\) 一定是三个 \(\text{LCA}\) 中与其余两个不相同的那个。

#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline T read(){
    T x=0;char ch=getchar();bool fl=false;
    while(!isdigit(ch)){if(ch=='-')fl=true;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return fl?-x:x;
}
#define read() read<int>()
#define LL long long
const int maxn = 5e5 + 10;
const int maxlog = 21;
int head[maxn],cnt=0;
struct edge{
	int to,nxt;
}e[maxn<<1];
inline void link(int u,int v){
	e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
}
int f[maxn][21],de[maxn];
void dfs(int u,int fa){
	f[u][0]=fa;de[u]=de[fa]+1;
	for(int j=1;j<maxlog;j++)f[u][j]=f[f[u][j-1]][j-1];
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==fa)continue;
		dfs(v,u);
	}
}
inline int getLCA(int x,int y){
	if(de[x]<de[y])swap(x,y);
	for(int j=maxlog-1;j>=0;j--)if(de[f[x][j]]>=de[y])x=f[x][j];
	if(x==y)return x;
	for(int j=maxlog-1;j>=0;j--)if(f[x][j]!=f[y][j])x=f[x][j],y=f[y][j];
	return f[x][0];
}
inline int dis(int x,int y){
	int LCA=getLCA(x,y);
	return de[x]+de[y]-2*de[LCA];
}
int n,m;
int main(){
	n=read();m=read();
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		link(u,v);link(v,u);
	}
	dfs(1,0);
	for(int i=1;i<=m;i++){
		int x=read(),y=read(),z=read();
		int L1=getLCA(x,y),L2=getLCA(y,z),L3=getLCA(x,z),LCA;
		if(L1==L2)LCA=L3;
		else if(L1==L3)LCA=L2;
		else LCA=L1;
		printf("%d %d\n",LCA,dis(x,LCA)+dis(y,LCA)+dis(z,LCA));
	}
	return 0;
}

P3629 [APIO2010] 巡逻

有一个 \(n\) 个节点的有根树,根为 \(1\)。要求从根节点 \(1\) 出发,遍历所有的边(进行一次树的遍历),最后回到 \(1\),每一步的代价是 \(1\)。

现要加入 \(K\in\{1,2\}\) 条非树边,使得满足上述条件的情况下,求代价最小是多少。

如果加入一条非树边,那么形成的环上的树边都从走 \(2\) 次变成了走 \(1\) 次。

贪心的选一定选树的直径,如果 \(K=1\),那么答案为 \(2(n-1)-L1+1\),其中 \(L1\) 是直径长度。

如果再连接一条非树边,那么又会形成一个新环。发现如果这个新环和旧环有交叉,那么交叉的所有树边又都会从走 \(1\) 次变回了走 \(2\) 次。

那么在第二次连接非树边时,可以对直径上的边权都从 \(1\) 改为 \(-1\),这样进行树形 DP 求树的新直径即可,答案为 \(2(n-1)-L1-L2+2\)

#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline T read(){
    T x=0;char ch=getchar();bool fl=false;
    while(!isdigit(ch)){if(ch=='-')fl=true;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return fl?-x:x;
}
#define read() read<int>()
#define LL long long
const int maxn = 1e5 + 5;
int head[maxn],cnt=1;
struct edge{
	int to,nxt,w;
}e[maxn<<1];
inline void link(int u,int v,int w){
	e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;e[cnt].w=w;
}
int n,K,t1,t2,L1,L2,f[maxn],mp[maxn],Fa[maxn],de[maxn];
void dfs1(int u,int fa){
	de[u]=de[fa]+1;
	if(de[u]>L1)L1=de[u],t1=u;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==fa)continue;
		dfs1(v,u);
	}
}
void dfs2(int u,int fa){
	Fa[u]=fa;
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==fa)continue;
		de[v]=de[u]+1;
		mp[v]=i;
		if(de[v]>L1)L1=de[v],t2=v;
		dfs2(v,u);
	}
}
void dfs(int u,int fa){
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==fa)continue;
		dfs(v,u);
		L2=max(L2,f[u]+f[v]+e[i].w);
		f[u]=max(f[u],e[i].w+f[v]);
	}
}
int main(){
	n=read();K=read();
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		link(u,v,1);link(v,u,1);
	}
	dfs1(1,0);
	L1=0;memset(de,0,sizeof de);
	dfs2(t1,0);
	if(K==1){
		cout<<2*(n-1)-(L1-1)<<endl;
		return 0;
	}
	while(t2!=t1){
		e[mp[t2]].w=e[mp[t2]^1].w=-1;
		t2=Fa[t2];
	}
	dfs(t1,0);
	cout<<2*n-L1-L2<<endl;
	return 0;
}

标签:11,2024.04,ch,回顾,int,de,read,maxn,getchar
From: https://www.cnblogs.com/Liang-sheng/p/18130094

相关文章

  • 2024/4/11
    今天大盘低开高走下午又低走,收红出上影线,这个反弹时之前预见的--市场连续下跌且到3000附件,又反弹的需求,高开低走且缩量,说明市场信心不足,调整大概率没有到位今天要批评一下自己,昨天明确说了大盘没有企稳,不要开仓,但是今天一反弹,尤其时工程机械汽车板块 东方电气快速拉升,因为前面......
  • Java基础学习 | 2024年4月11日
    变量1.类变量(静态变量):前面用static修饰,表示所有子类都共用同一个属性值,可以直接用类名来访问静态变量,也可以通过实例名来访问静态变量。即无论创建多少个类实例,静态变量在内存中只有一份拷贝,被所有实例共享。举例:点击查看代码publicclassMyClass{publicstaticintc......
  • 2024.4.11
    2024.4.11【虚怀若谷,戒骄戒躁。】Thursday三月初三<theme=oi-"language">这个好东西叫pb_ds!!!#include<bits/extc++.h>usingnamespace__gnu_cxx;usingnamespace__gnu_pbds;堆操作/数据结构配对堆二叉堆左偏树二项堆斐波那契堆代码pairing_heap_t......
  • Windows 11 专业工作站版 是目前最强的系统吗?
    Windows11专业工作站版是微软针对专业人士和企业推出的操作系统,它在Windows11专业版的基础上增加了许多功能和性能增强,使其成为目前最强大的系统。性能强劲Windows11专业工作站版支持最多4个CPU和6TB内存,可轻松满足高性能工作负载的需求。它还支持ReFS文件系统......
  • 接口实现-删除文章(2024-4-11)
    代码量:500时间:5h博客量:1今天写了Android的前端页面,和页面功能的基本实现,剩下最难的接口调用方面了下面是跟的项目的一个简单接口//controller@DeleteMappingpublicResultdelete(Integerid){articleService.delete(id);returnResult.success();......
  • 14--爬虫回顾和重点经验
    01.浏览器#一个网页的加载全过程1.服务器端渲染html的内容和数据在服务器进行融合.在浏览器端看到的页面源代码中.有你需要的数据2.客户端(浏览器)渲染html的内容和数据进行融合是发生在你的浏览器上的.这个过程一般通过脚本来完成(javascript)我们......
  • 2024-04-11 15:45
    今天终于是写上日记了,之前要么没时间要么就不想写,过完年后有一大片空白期,领导看我们很清闲,就给我们各自安排学习任务,我学习Flutter相关知识,但是学习了之后发现Flutter是个框架,里边的语言是dart语言,发现还的学习dart,还要整理学习文档,哦我的天之前的东西都没明白就又学习另外一种语......
  • 2024.04.11NOIP模拟赛 #1 记录
    2024.04.11NOIP模拟赛#1记录AT_arc160_e[ARC160E]MakeBiconnected给你一棵\(n\)个节点由无向边组成的二叉树,树上每个点有权值\(w_i\)。你可以把两个点之间连无向边,如果将\(u\)与\(v\)连边,代价是\(w_u+w_v\)。请给出一种连边方式,使得连边后,图中去掉任何一个点仍然......
  • 3 数字麦阵列声源定位模组 AR1105
    一,产品概述:AR1105是一款专用于音源定位寻向的模组。模组选用行业最新算法内核DSP芯片,并综合简单易用的原则而设计。AR1105模组需要搭配3颗间距都为10mm数字麦克风,利用每2颗数字麦克风组合的心形指向性,能够方便快速的辨识圆周6个方向的音源方向。对比常规的需要......
  • Windows 11 cmd终端命令提示符图标路径
    前言全局说明一、默认路径ms-appx:///ProfileIcons/{0caa0dad-35be-5f56-a8ff-afceeeaa6101}.png二、实际路径C:\ProgramFiles\WindowsApps\Microsoft.WindowsTerminal_1.19.10573.0_x64__8wekyb3d8bbwe\ProfileIconsWindowsApps文件夹是隐藏文件夹直接打开C:\Pro......