列表

详情


NC50510. 皇宫看守

描述

太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫。
皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状,某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。
可是陆小凤手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。
帮助陆小凤布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。

输入描述

输入中数据描述一棵树,描述如下:
第一行n,表示树中结点的数目。
第二行至第n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号,在该宫殿安置侍卫所需的经费k,该边的儿子数m,接下来m个数,分别是这个节点的m个儿子的标号
对于一个n个结点的树,结点标号在1到n之间,且标号不重复。

输出描述

输出最少的经费

示例1

输入:

6
1 30 3 2 3 4
2 16 2 5 6
3 5 0
4 4 0
5 11 0
6 5 0

输出:

25

说明:

有六个区域被安排的情况如左图所示。
如右图,灰色点安排了警卫,2号警卫可以观察1,2,5,6,3号警卫可以观察1,3,4号警卫可以观察1,4。
总费用:16+5+4=25

原站题解

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

C++(clang++ 11.0.1) 解法, 执行用时: 5ms, 内存消耗: 512K, 提交时间: 2023-07-30 23:03:14

#include<bits/stdc++.h>
using namespace std;
int k[1501],f[1501][3];
vector <int> g[1501];
void dfs(const int &u,const int &fa){
	f[u][0] = k[u];
	bool flag = 1;
	int x = INT_MAX;
	for (auto v : g[u])
		if (v != fa){
			dfs(v,u);
			f[u][0] += min(f[v][0],min(f[v][1],f[v][2]));
			f[u][1] += min(f[v][0],f[v][2]);
			if (f[v][0] <= f[v][2]){
				f[u][2] += f[v][0];
				flag = 0;
			}else{
				f[u][2] += f[v][2];
				x = min(x,f[v][0] - f[v][2]);
			}
		}
	if (flag)f[u][2] += x;
}
int main(){
	int n,u,m,v,i;
	cin>>n;
	for (i = 0;i < n;i++){
		cin>>u;
		cin>>k[u]>>m;
		while (m--){
			cin>>v;
			g[u].push_back(v);
			g[v].push_back(u);
		}
	}
	dfs(1,0);
	cout<<min(f[1][0],f[1][2]);
	return 0;
}

上一题