【算法每日一练】动态规划,图论(换根dp)会议 ,医院设置

目录

[题目: 会议](#题目: 会议)

思路:

题目:医院设置

思路:


题目: 会议

思路:

首先,阅读题目可以看出来,这道题目实际上就是求树的重心。

树的重心

定义:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,达到的效果是生成的多棵树尽可能平衡。

举个例子:

我们不妨设置d[i]表示以此点为根的所有点总距离和,cnt[i]表示以此为根的节点数

我们首先知道d[1]=16,cnt[1]=10我们来看d[2]应该怎么求,我们发现相对于d[1]来说,如果设2为最佳点,2,5,6其距离-1,剩下的1,4,3,7,8,9,10到其距离+1。

故:d[2]=d[1] - 3 + 7 =20

其中3是子根2对应的节点数cnt[2],7是1为子根对应的节点数cnt[1]-cnt[2]

得:d[i]=d[fa]-cnt[i]+(cnt[1]-cnt[i])

那么只需要先dfs求出来d[1]和每个点的cnt[i]。然后就可以进行dp最终求出所有点的d[i]。

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N=50005;
int minn=0x3f3f3f3f,ans,n,d[N],cnt[N];
vector<int>ve[N];
void dfs(int u,int fa,int len){//一定别走fa回去
	cnt[u]++;//先加上自己
	for(int i=0;i<ve[u].size();i++){
		int v=ve[u][i];
		if(v==fa)continue;
		dfs(v,u,len+1);//先求孩子的cnt,之后求自己cnt
		cnt[u]+=cnt[v];
	}
	d[1]+=len;//最后求d[1]
}
void dp(int u,int fa){
	for(int i=0;i<ve[u].size();i++){
		int v=ve[u][i];
		if(v==fa)continue;
		d[v]=d[u]-2*cnt[v]+cnt[1];
		dp(v,u);//这里对自己进行转移更新,再对孩子的更新
	}
}
int main(){
	cin>>n;int a,b;
	for(int i=1;i<n;i++){
		cin>>a>>b;
		ve[a].push_back(b);
		ve[b].push_back(a);
	}
	dfs(1,0,0);
	dp(1,0);
	for(int i=1;i<=n;i++){
		if(d[i]<minn)
			minn=d[i],ans=i;
	}
	cout<<ans<<" "<<minn;
}

上面我打注释的地方一定要理解

题目:医院设置

思路:

还是一道求树的重心题。不过是每个点都有一个权值。那么把权值当成"另一个世界的节点数"就好了。然后不断求cnt,之后dp就行。

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N=500;
int ans=0x3f3f3f3f,n,d[N],cnt[N],w[N];
vector<int>ve[N];
void dfs(int u,int fa,int len){
	cnt[u]=w[u];//这里还是先加自己
	for(int i=0;i<ve[u].size();i++){
		int v=ve[u][i];
		if(v==fa)continue;
		dfs(v,u,len+1);
		cnt[u]+=cnt[v];
	}
	d[1]+=len*w[u];//更新d[1]也要变一下
}
void dp(int u,int fa){
	for(int i=0;i<ve[u].size();i++){
		int v=ve[u][i];
		if(v==fa)continue;
		d[v]=d[u]+cnt[1]-cnt[v]*2;
		dp(v,u);
	}
	ans=min(ans,d[u]);
}
int main(){
	cin>>n;int c,a,b;
	for(int i=1;i<=n;i++){
		cin>>c>>a>>b;
		w[i]=c;//注意输入方式
		if(a)ve[i].push_back(a),ve[a].push_back(i);
		if(b)ve[i].push_back(b),ve[b].push_back(i);
	}
	dfs(1,0,0);
	dp(1,0);
	cout<<ans;
}
相关推荐
知来者逆11 分钟前
计算机视觉——速度与精度的完美结合的实时目标检测算法RF-DETR详解
图像处理·人工智能·深度学习·算法·目标检测·计算机视觉·rf-detr
阿让啊15 分钟前
C语言中操作字节的某一位
c语言·开发语言·数据结构·单片机·算法
এ᭄画画的北北16 分钟前
力扣-160.相交链表
算法·leetcode·链表
草莓啵啵~43 分钟前
搜索二叉树-key的搜索模型
数据结构·c++
爱研究的小陈1 小时前
Day 3:数学基础回顾——线性代数与概率论在AI中的核心作用
算法
渭雨轻尘_学习计算机ing1 小时前
二叉树的最大宽度计算
算法·面试
丶Darling.2 小时前
26考研 | 王道 | 数据结构 | 第八章 排序
数据结构·考研·排序算法
BB_CC_DD2 小时前
四. 以Annoy算法建树的方式聚类清洗图像数据集,一次建树,无限次聚类搜索,提升聚类搜索效率。(附完整代码)
深度学习·算法·聚类
我也不曾来过12 小时前
list底层原理
数据结构·c++·list
梁下轻语的秋缘3 小时前
每日c/c++题 备战蓝桥杯 ([洛谷 P1226] 快速幂求模题解)
c++·算法·蓝桥杯