Codeforces Round 121 (Div. 1) C题 Fools and Roads(LCA最近公共祖先,树上差分)

news/2024/12/22 0:38:39/

题目链接

https://codeforces.com/problemset/problem/191/C

思路

一道比较板的LCA和树上差分的题。

先预处理出这棵树的LCA,之后对于每一对 a i , b i a_{i},b_{i} ai,bi,在树上做差分,最后用 d f s dfs dfs处理差分数组即可。

树上差分记得从叶子向根节点,不要弄反。

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;
int n, k;
int u[N], v[N];
int d[N];//差分数组
struct LCA
{vector<vector<int>>mp;vector<int>depth;vector<vector<int>>fa;LCA() {}LCA(int n) {init(n);}void init(int n){mp.resize(n + 1);depth.resize(n + 1);fa.resize(n + 1, vector<int>(20));}void add_edge(int a, int b){//建双向边mp[a].push_back(b);mp[b].push_back(a);}void bfs(int root){fill(depth.begin(), depth.end(), inf);depth[0] = 0, depth[root] = 1;queue<int>q;q.push(root);while (q.size()){int u = q.front();q.pop();for (int i = 0; i < mp[u].size(); i++){int j = mp[u][i];if (depth[j] > depth[u] + 1){depth[j] = depth[u] + 1;q.push(j);fa[j][0] = u;for (int k = 1; k <= 19; k++){fa[j][k] = fa[fa[j][k - 1]][k - 1];}}}}}int lca(int a, int b){if (depth[a] < depth[b]) swap(a, b);for (int k = 19; k >= 0; k -- )if (depth[fa[a][k]] >= depth[b])a = fa[a][k];if (a == b) return a;for (int k = 19; k >= 0; k -- )if (fa[a][k] != fa[b][k]){a = fa[a][k];b = fa[b][k];}return fa[a][0];}
};
void solve()
{cin >> n;LCA tree(n);map<int, int>st;for (int i = 1; i < n; i++){cin >> u[i] >> v[i];tree.add_edge(u[i], v[i]);st[u[i] * n + v[i]] = i;st[v[i] * n + u[i]] = i;}tree.bfs(1);cin >> k;for (int i = 1, a, b; i <= k; i++){cin >> a >> b;int zu = tree.lca(a, b);if (zu != a && zu != b){d[a]++, d[b]++, d[zu] -= 2;}else{if (zu == a) d[b]++, d[a]--;else d[a]++, d[b]--;}}auto dfs1 = [&](auto dfs1, int u, int fu)->void {for (int j : tree.mp[u]){if (j == fu) continue;dfs1(dfs1, j, u);d[u] += d[j];}};dfs1(dfs1, 1, -1);//树上差分->前缀和vector<int>ans(n);auto dfs2 = [&](auto dfs2, int u, int fu)-> void {for (int j : tree.mp[u]){if (j == fu) continue;int idx = st[u * n + j];ans[idx] = d[j];dfs2(dfs2, j, u);}};dfs2(dfs2, 1, -1);for (int i = 1; i < n; i++){cout << ans[i] << " ";}cout << endl;
}
signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int test = 1;// cin >> test;for (int i = 1; i <= test; i++){solve();}return 0;
}

http://www.ppmy.cn/news/1534408.html

相关文章

“衣依”服装销售平台:Spring Boot技术架构剖析

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常适…

VS Code 图形化合并工具

VS Code 图形化合并工具能够帮助你更直观地进行代码合并和解决冲突 1. VS Code 内置的 Git 合并工具 VS Code 自带的 Git 支持已经非常强大&#xff0c;能够在合并冲突时提供直观的图形化界面&#xff0c;帮助你轻松解决冲突。以下是使用内置功能的步骤&#xff1a; 步骤一&…

中安未来 OCR—— 开启高效驾驶证识别新时代

在数字化飞速发展的今天&#xff0c;光学字符识别&#xff08;OCR&#xff09;技术正逐渐成为各行业提高效率、降低成本的重要工具。而中安未来的 OCR 技术&#xff0c;以其卓越的性能和广泛的应用场景&#xff0c;在众多 OCR 解决方案中脱颖而出。其中&#xff0c;驾驶证识别功…

基于大数据技术的足球数据分析与可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

yolov8/9/11模型在中医舌苔分类中的应用【代码+数据集+python环境+GUI系统】

yolov8、9、11模型在中医舌苔分类中的应用【代码数据集python环境GUI系统】 背景意义 目前随着人们生活水平的不断提高&#xff0c;对于中医主张的理念越来越认可&#xff0c;对中医的需求也越来越多。 传统中医的舌诊主要依赖于医生的肉眼观察&#xff0c;仅仅通过这种人工诊…

事后被动处置向事前主动预警转变的智慧工业开源了

智慧工业视觉监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。用户只需在界面上…

用责任链模式改造 if else

我的上一篇文章&#xff0c;因为if else 多了&#xff0c;捣鼓很久&#xff0c;今天用责任链模式改造一下。 代码写着写着&#xff0c;if else if 逻辑忘记了&#xff0c;哎。。。-CSDN博客 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09; 1. 什么是责任…

第九章---for循环及在STL的应用(vector\map\set\list\for_each)、嵌套while、while 统一输出、do-while

在C中&#xff0c;循环语句用于重复执行一段代码&#xff0c;直到指定的条件不再满足。C 提供了几种循环机制&#xff0c;下面将详细讲解每种循环语句的用法和特点。 1. for 循环 for 循环是最常用的循环结构之一&#xff0c;它有三种基本形式&#xff1a; 基本形式&#xf…