列表

详情


NC223205. B 天平

描述

小 Y 有 m 种无穷多的物品以及一根杆子。他希望用它们做成一根如下的天平。

天平的性质是对于任意一个物品下面连着的杆子,在不计杆重的情况下可以平衡。同时,不允许存在某个点到其左右连着的物品杆长不是整数。

现在小 Y 想要知道,要想挂 n 个物品在一个固定形状的天平上且天平平衡,最少需要用的杆子的长度。

形式化的,现有一棵有 n 个有 0 或 2 个儿子的节点的二叉树。你可以给每个节点赋权给定的 m 个数中的任意一个。记每个节点的子树的和为 s_i

随后你需要给每个非叶子点赋正整数权值 L_i, R_i 使得 。求所有 L 和 R 的和的最小值。

输入描述

第一行,n,m。

第二行,m 个数,表示每种物品的质量。

接下来若干行,每行三个数 u,x,y。表示在 u 物品下的两个物品编号分别为 x,y。行数是可以推知的。

保证整个树形结构的根是 1。

输出描述

一行,表示最终的答案。

示例1

输入:

3 3
2 3 4
1 2 3

输出:

2

示例2

输入:

7 3
1 3 4
1 2 3
3 4 5
4 6 7

输出:

8

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 379ms, 内存消耗: 25572K, 提交时间: 2021-09-17 19:17:12

#include<bits/stdc++.h>
#define N 55
#define M 2505
#define pb push_back
using namespace std;
int n,m,w[N],f1[M][M],tmp[M],siz[M],f[N][M],ans=2e9;
vector<int>adj[N];
void cmin(int &x,int y){x=x<y?x:y;}
void dfs(int x){
	siz[x]=1;
	if(!adj[x].empty()){
		int X=adj[x][0],Y=adj[x][1];
		dfs(X),dfs(Y),siz[x]+=siz[X],siz[x]+=siz[Y];
		memset(tmp,0x3f,sizeof(tmp));
		for(int i=1;i<=siz[X]*50;i++)
			for(int j=1;j<=siz[Y]*50;j++)cmin(tmp[i+j],f[X][i]+f[Y][j]+(i+j)/f1[i][j]);
	}else{
		memset(tmp,0x3f,sizeof(tmp));
		tmp[0]=0;
	}
	for(int i=1;i<=m;i++)for(int j=0;j<=siz[x]*50;j++)cmin(f[x][j+w[i]],tmp[j]);
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++)cin>>w[i];
	for(int i=1,u,x,y;i*2<=n;i++)cin>>u>>x>>y,adj[u].pb(x),adj[u].pb(y);
	for(int i=1;i<M;i++)for(int j=1;j<M;j++)f1[i][j]=__gcd(i,j);
	memset(f,0x3f,sizeof(f)),dfs(1);
	for(int i=0;i<M;i++)cmin(ans,f[1][i]);
	cout<<ans<<'\n';
	return 0;
}

上一题