娄居吉勾

题目链接:YBT2023寒假Day10 C

题目大意

有一个 n 个点 m 条边的无向连通图,每个点至多在 k 个简单环上。
然后有 q 个操作,标记一个没有标记过的点,或者给你一个点求它得到所有标记点中距离最短的点的距离。

思路

如果 k = 0 k=0 k=0,就可以简单的点分树。
就建出来,然后对于每个子树维护里面所有点的标记点到根(重心)的最短距离。
修改的时候直接枚举点分数上到根的链,里面的每个点分别更改一下最短距离即可。
询问的时候,我们枚举这个点和标记点在点分树上的 LCA 的位置(也是枚举到根的链上的点),用到 LCA 的距离加 LCA 子树的最短距离即可。
(不用怕又走回自己的子树,因为边权非负肯定不优)

那这个时候不能用的问题是啥,就是它不一定经过 LCA 的位置。
那这条路径经过了什么,一定经过了链接 LCA 两个不同子树的非树边。
而且一个非树边可以确定一个简单环,所以这些边的数量是不超过 k ⩽ 10 k\leqslant 10 k⩽10 的。
那我们在这些边的两端位置统计即可。

那对于多组询问,我们可以预处理出每个点作为 LCA 或者非树边两端点只走子树内带你到里面每个点的最短距离,并维护出每个点到它每个 LCA 再到标记点和这个 LCA 下的另一子树得到标记点的最短距离。
(其实两个可以说是实现上一样的)
然后就可以了。

代码

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#define INF 0x3f3f3f3f3f3f3f3fusing namespace std;const int N = 1e5 + 100;
struct node {int to, nxt;
}e[N << 2];
int n, m, k, le[N], KK, sz[N], root, root_sum;
int fa[N], deg[N], dis[51][N], f[N];
queue <int> q;
bool in[N], ok[N];void add(int x, int y) {e[++KK] = (node){y, le[x]}; le[x] = KK;
}void dfs0(int now) {sz[now] = 1; in[now] = 1;for (int i = le[now]; i; i = e[i].nxt)if (!in[e[i].to] && !ok[e[i].to]) {dfs0(e[i].to); sz[now] += sz[e[i].to];}
}void dfs1(int now, int father, int all) {int sum = all - sz[now]; in[now] = 1;for (int i = le[now]; i; i = e[i].nxt)if (!in[e[i].to] && !ok[e[i].to]) {dfs1(e[i].to, now, all); sum = max(sum, sz[e[i].to]);}if (sum < root_sum) root_sum = sum, root = now;
}void slove(int fr, int d) {while (!q.empty()) q.pop();q.push(fr);dis[d][fr] = 0;while (!q.empty()) {int now = q.front(); q.pop();for (int i = le[now]; i; i = e[i].nxt)if (!ok[e[i].to] && !dis[d][e[i].to] && e[i].to != fr) {dis[d][e[i].to] = dis[d][now] + 1; q.push(e[i].to);}}
}void clear(int now) {in[now] = 0;for (int i = le[now]; i; i = e[i].nxt)if (!ok[e[i].to] && in[e[i].to]) {clear(e[i].to);}
}void work(int now, int father) {ok[now] = 1; fa[now] = father;deg[now] = deg[father] + 1;slove(now, deg[now]);for (int i = le[now]; i; i = e[i].nxt)if (!ok[e[i].to]) {clear(e[i].to); dfs0(e[i].to); root_sum = sz[e[i].to] + 1; clear(e[i].to); dfs1(e[i].to, 0, sz[e[i].to]);work(root, now);}
}void insert(int x) {int now = x;while (now) {f[now] = min(f[now], dis[deg[now]][x]);now = fa[now];}
}int query(int x) {int now = x, re = INF;while (now) {re = min(re, f[now] + dis[deg[now]][x]);now = fa[now];}return re;
}int main() {freopen("graph.in", "r", stdin);freopen("graph.out", "w", stdout);scanf("%d %d %d", &n, &m, &k);for (int i = 1; i <= m; i++) {int x, y; scanf("%d %d", &x, &y);add(x, y); add(y, x);}clear(1); dfs0(1); root_sum = n + 1; clear(1); dfs1(1, 0, sz[1]);work(root, 0);for (int i = 1; i <= n; i++) f[i] = INF;int Q; scanf("%d", &Q);while (Q--) {int t, x;scanf("%d %d", &t, &x);if (t == 1) insert(x);if (t == 2) printf("%d\n", query(x));}return 0;
}

【YBT2023寒假Day10 C】娄居吉勾(点分树)相关推荐

  1. 【YBT2023寒假Day10 B】随机游走(记忆化搜索)

    随机游走 题目链接:YBT2023寒假Day10 B 题目大意 有 n 个点排成环,你一开始在 1 号点,每次可以等概率选择左边跳两格,左边跳一格,右边跳一格,右边跳两格. 走到一个走过的点就停止. ...

  2. 【YBT2023寒假Day11 B】催眠大师(费用流)

    催眠大师 题目链接:YBT2023寒假Day11 B 题目大意 有一个 n*n 的棋盘,有一些位置有障碍. 然后定义棋盘上两个位置能相互攻击当且仅当在同一行或同一列,且之间的所有位置都没有障碍. 多次 ...

  3. 【YBT2023寒假Day3 C】樱桃莓莓(凸包)(线段树)

    樱桃莓莓 题目链接:YBT2023寒假Day3 C 题目大意 给你一棵有根数,点有 a,b 两种权值. 然后一个点的分数是它以及它所有祖先的 a 权值和的绝对值乘上 b 权值和的绝对值. 然后有两种操 ...

  4. 【YBT2023寒假Day9 B】买棉花糖(DP)(分治)

    买棉花糖 题目链接:YBT2023寒假Day9 B 题目大意 有 n 个商店,每个商店有 ci 个物品,原价是 ai,你在一个商店买的物品越多,下一个买的就越少,每次减少 di 块钱. 然后有 q 次 ...

  5. 【YBT2023寒假Day1 B】不跪模样(树链剖分)(线段树)

    不跪模样 题目链接:YBT2023寒假Day1 B 题目大意 给你一棵有根数,点有点权,两种操作: 对于所有 x 子树内与 x 距离不超过 2 的点,将其点权加 v. 询问 x 子树中,满足 i< ...

  6. 【YBT2023寒假Day4 C】樱桃莓莓(交互)(四毛子分块)(线段树)

    樱桃莓莓 题目链接:YBT2023寒假Day4 C 题目大意 有一个黑盒操作满足交换律和结合律,有 n 个数,q 次询问,每次选 m 个下标,你要计算所有不包含那 m 个下标的数进行黑盒操作之后的结果 ...

  7. 【YBT2023寒假Day3 A】千与千寻(期望DP)(高斯消元)

    千与千寻 题目链接:YBT2023寒假Day3 A 题目大意 一个 n*m 的平面,你要从 (0,0) 走到 (x,y),你等概率的向上或向右走,然后当你走到 (n-1,i) 再往右走,就是 (0,i ...

  8. 【YBT2023寒假Day11 A】海妖沙龙(计算几何)

    海妖沙龙 题目链接:YBT2023寒假Day11 A 题目大意 平面上有 n 个点,然后对于一个排列,如果按顺序走对于的点,会形成若干个线段组成的路径,然后你从前一个线段走到下一个线段端点时候,你需要 ...

  9. 【YBT2023寒假Day13 C】百里守约(Boruvka算法)(扫描线)(线段树)

    百里守约 题目链接:YBT2023寒假Day13 C 题目大意 有一个 n*n 的矩阵,一开始里面都是 0,多次操作,每次把一个子矩阵里面的值都增加每次给出的 w. 然后全部操作完之后构造一个 n 个 ...

最新文章

  1. GitHub 热榜:中国博士开发可交互全球疫情地图,登上柳叶刀!
  2. Chrome资深粉热衷的10个必备扩展程序
  3. 皮一皮:大自然的力量你无法想象...
  4. pybind 编码h264
  5. bsc是指什么_为什么KPI令人厌恶?中小企业不要乱用KPI!
  6. sqlserver递归
  7. Qt linux双屏,qt5 多屏显示
  8. php redis sorted set,Redis 有序集合(sorted set)
  9. python 利用栈实现复杂计算器
  10. 图像处理(十三)LBP特征提取
  11. 通信线路工程验收规范_老杨一建通信学堂通信线路工程施工技术
  12. dataframe数据之间求补集
  13. 用好小程序码这张小程序专有的名片
  14. Python利用hadoop Streaming编写的Map-Reduce程序命令运行和本地调试运行
  15. log4j中配置LOG_HOME无效
  16. GMA Round 1 YGGDRASIL
  17. 高精度乘法(正负数皆可(Bull Math)POJ)
  18. 【转载】关于 .Net 逆向的那些工具:反编译篇
  19. [MemTest太慢? 来试试这个压力更大吧!]分享一个快速测试内存超频出错的软件-TM5(和国外大佬的极限自定义配置)
  20. Win10 桌面图标字体怎么单独换成深色,设置白色壁纸后图标字体看不见

热门文章

  1. 数据挖掘之数据清洗(缺失值,异常值)
  2. 手机游戏市场分析-3G手机开发公开课-东方尚智,3g数字内容学院
  3. 手机用蓝牙键盘好使吗_平板手机上能不能用蓝牙键盘 平板手机的蓝牙键盘使用方法...
  4. 第八届蓝桥杯-第四题方格分割
  5. 系统提示病毒文件不理会?账号拿来吧你!
  6. 与师生谈人工智能1:智乎哉?
  7. 「更新方法」iOS16.4更新方法及固件下载
  8. 大牛车金融获投1000万天使轮投资,将继续拓展线下分公司营业点
  9. Netty 单机百万连接测试
  10. 苹果手机sim卡无效怎么办_苹果手机待机时间短怎么办