【图论】Linova and Kingdom—CF1336A

Linova and Kingdom---CF1336A
参考文章

思路

1 1 1 号节点为根节点。很容易想到,工业城市在树的下边,旅游城市在树的上边。具体来说,如果节点 u u u 是工业城市,那么它的子树的所有节点一定都是工业城市;如果节点 u u u 是旅游城市,那么它到根节点的路径上的所有城市都是旅游城市。

我们先把所有城市认定为工业城市,然后在与工业城市直接相连的旅游城市中选出"将其变为工业城市提供的贡献值"最大的城市,并将其变为工业城市。

城市的贡献的计算方法:当前点的子树的节点数 - (当前点的深度 - 1)。

可以利用用优先队列来选出最佳的城市,然后再将新产生的满足条件的城市压入队列。

由于我们选出的"贡献点最大的城市"的前提是这个点(设为 w w w 点)的子树上所有点都是工业城市,并且与根节点路径上的所有点都是旅游城市。那么如果后边的操作把 w w w 点的子节点给变成了旅游城市,那么不就不满足这个条件了吗?

请认真考虑我们是如何计算计算一个边界处的旅游城市如果变为工业城市后可以提供的贡献的:当前点的子树的节点数 - (当前点的深度 - 1)。 w w w 的贡献是相对于" w w w 点及 w w w 点到根节点路径上都是旅游城市的条件",也就是这种计算贡献的方法考虑了上一个状态,并非独立计算某一个点的贡献。

C o d e Code Code

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
#define sz(a) ((int)a.size())
#define all(a) a.begin(), a.end()
using namespace std;
using PII = pair<int, int>;
using i128 = __int128;
const int N = 2e5 + 10;

int n, k;
int contri[N];

void solve() {
	cin >> n >> k;
	
	vector<vector<int>> g(n + 1);
	for (int i = 1; i <= n - 1; i ++) {
		int a, b; cin >> a >> b;
		g[a].push_back(b);
		g[b].push_back(a);
	}
	
	// 计算深度和子树中节点数量
	vector<int> deep(n + 1, -1), son_num(n + 1);
	auto dfs = [&] (auto dfs, int u) ->int {
		int sum = 1;
		for (auto v : g[u]) {
			if (deep[v] == -1) {
				deep[v] = deep[u] + 1;
				sum += dfs(dfs, v);
			}
		}
		son_num[u] = sum;
		return sum;
	};
	deep[1] = 1;
	dfs(dfs, 1);
	// 计算每个点的贡献
	for (int i = 1; i <= n; i ++) {
		son_num[i] --;
		contri[i] = son_num[i] - (deep[i] - 1);
	}
	
	int res = 0;
	k = n - k;
	vector<int> st(n + 1, 0); // 标记是否为旅游城市/已经来过
	
	priority_queue<PII, vector<PII>> q; // [贡献,节点] 降序优先队列
	q.emplace(contri[1], 1);
	while (not q.empty() && k --) {
		auto [f, s] = q.top(); q.pop();
		st[s] = 1;
		res += f;
		for (auto v : g[s]) {
			if (not st[v]) {
				q.emplace(contri[v], v);
			}
		}
	}
	
	cout << "         ";
	cout << res << "\n";
}

signed main() {
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int T = 1;
//	cin >> T; cin.get();
	while (T --) solve();
	return 0;
}
相关推荐
平凡但不平庸的码农2 小时前
Go Slice 详解
算法·golang
Jasmine_llq6 小时前
《B3867 [GESP202309 三级] 小杨的储蓄》
算法·循环遍历·数组累加(模拟)·索引定位·顺序输出
啦啦啦_99996 小时前
案例之 逻辑回归_电信用户流失预测
算法·机器学习·逻辑回归
风筝在晴天搁浅6 小时前
快手/字节 CodeTop LeetCode 415.字符串相加
算法·leetcode
DragonnAi6 小时前
猫咪如厕检测与分类识别系统系列【十四】 项目结构重新整理-即将开源完整算法
算法·开源
机器视觉_Explorer7 小时前
【halcon】编程技巧:鼠标擦除
图像处理·人工智能·深度学习·算法·视觉检测
灵智实验室8 小时前
PX4状态估计技术EKF2详解(二):EKF2 误差状态动力学与协方差传播
算法·无人机·px 4
米粒18 小时前
力扣算法刷题 Day 64 Floyd算法 & A* 算法 & 总结篇
算法·leetcode·职场和发展
XX風8 小时前
OpenGL中Face culling 面剔除的具体实现
算法·图形渲染
IT猿手8 小时前
光伏模型参数估计:基于山羊优化算法(GOA )的光伏模型参数辨识问题求解研究,免费提供完整MATLAB代码链接
开发语言·算法·matlab·群智能优化算法·智能优化算法·光伏模型参数估计·光伏模型参数辨识