前置:双联通分量、圆方树、树链剖分

什是是广义圆方树

圆方树是针对于仙人掌建树,而广义圆方树是针对无向图建树,对于一个无向图

  • 无向图中的所有点 → 广义圆方树中的所有圆点
  • 无向图中的一个双联通分量 → 广义圆方树中的其中一个方点,这个方点向当前双联通分量中的所有点连边
  • 无向图中的一条不在任何环中的边 → 广义圆方树中的其中一个方点,这个方点向当前边的两个端点连边

一张非常形象的图,来源于一个课件

其实看了这个图应该就什么都懂了,一些性质也很容易被发现hh

例如:广义图方树中一定是圆点方点相间,即圆点的父亲一定是方点,方点的父亲一定是圆点

一道例题:

https://codeforc.es/contest/487/problem/E

中文翻译:https://www.luogu.org/problemnew/show/CF487E

中文题意在上面那个链接里面

考虑起点u终点v,很容易发现答案就是u点到v点过程中经过的所有双联通分量中权值最小的那个点

建立广义圆方树,规定

  • 所有圆点的权值 → 原图中点的权值
  • 所有方点的权值 → 所有儿子的权值最小值(别忘了它所有儿子一定都是圆点)

对于每次询问

  • 如果u和v的LCA是圆点 → 答案就是u到v这条路径的最小值
  • 如果u和v的LCA是方点 → 答案就是u到v这条路径的最小值和方点父亲的值的最小值

修改就不用说了,然后这完全就是个树上修改+查询的模板问题,直接树链剖分+线段树就搞定了

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<set>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
vector<int> G[200005], T[205005];
multiset<int> Set[205005];
stack<int> st;
int n, t, cnt, val[205005], Time[205005], low[205005];
typedef struct RST
{int tre[814396];int t, fa[205005], size[205005], hson[205005], top[205005], dep[205005], rak[205005], id[205005];void Sech1(int u, int p){int v, i;fa[u] = p, dep[u] = dep[p]+1;if(fa[u]>=n+1)Set[fa[u]].insert(val[u]);size[u] = 1;for(i=0;i<T[u].size();i++){v = T[u][i];if(v==p)continue;Sech1(v, u);size[u] += size[v];if(size[v]>size[hson[u]])hson[u] = v;}}void Sech2(int u, int p){int i, v;top[u] = p;rak[u] = ++t, id[t] = u;if(hson[u])Sech2(hson[u], p);for(i=0;i<T[u].size();i++){v = T[u][i];if(v==fa[u] || v==hson[u])continue;Sech2(v, v);}}void Update(int l, int r, int x, int a, int b){int m;if(l==r){tre[x] = b;return;}m = (l+r)/2;if(a<=m)Update(l, m, x*2, a, b);elseUpdate(m+1, r, x*2+1, a, b);tre[x] = min(tre[x*2], tre[x*2+1]);}int Query(int l, int r, int x, int a, int b){int m, now;now = 1044266558;if(l>=a && r<=b)return tre[x];m = (l+r)/2;if(a<=m)now = min(now, Query(l, m, x*2, a, b));if(b>=m+1)now = min(now, Query(m+1, r, x*2+1, a, b));return now;}int TreQuery(int x, int y){int now, p1, p2;p1 = top[x], p2 = top[y], now = 1044266558;while(p1!=p2){if(dep[p1]<dep[p2])swap(p1, p2), swap(x, y);now = min(now, Query(1, cnt, 1, rak[p1], rak[x]));x = fa[p1], p1 = top[x];}if(dep[x]>dep[y])swap(x, y);now = min(now, Query(1, cnt, 1, rak[x], rak[y]));if(x>=n+1)now = min(now, val[fa[x]]);return now;}
}RT;
RT RST;
void Trajan(int u, int p)
{int i, v, now;st.push(u);Time[u] = low[u] = ++t;for(i=0;i<G[u].size();i++){v = G[u][i];if(v==p)continue;if(Time[v]==0){Trajan(v, u);low[u] = min(low[u], low[v]);if(low[v]>=Time[u]){T[++cnt].push_back(u);T[u].push_back(cnt);while(st.empty()==0){now = st.top(), st.pop();T[cnt].push_back(now);T[now].push_back(cnt);if(now==v)break;}}}elselow[u] = min(low[u], Time[v]);}
}
void Update(int u, int c, int d)
{Set[u].erase(Set[u].find(c));Set[u].insert(d);
}
int main(void)
{char ch;int i, m, x, y, T;scanf("%d%d%d", &n, &m, &T);for(i=1;i<=n;i++)scanf("%d", &val[i]);cnt = n;for(i=1;i<=m;i++){scanf("%d%d", &x, &y);G[x].push_back(y);G[y].push_back(x);}Trajan(1, 0);RST.Sech1(1, 0);RST.Sech2(1, 1);for(i=1;i<=n;i++)RST.Update(1, cnt, 1, RST.rak[i], val[i]);for(i=n+1;i<=cnt;i++)RST.Update(1, cnt, 1, RST.rak[i], *Set[i].begin());while(T--){scanf(" %c%d%d", &ch, &x, &y);if(ch=='C'){RST.Update(1, cnt, 1, RST.rak[x], y);if(RST.fa[x]){Update(RST.fa[x], val[x], y);RST.Update(1, cnt, 1, RST.rak[RST.fa[x]], *Set[RST.fa[x]].begin());}val[x] = y;}elseprintf("%d\n", RST.TreQuery(x, y));}return 0;
}

广义圆方树+树链剖分+set(Codeforces Round #278 (Div. 1): E. Tourists)相关推荐

  1. [学习笔记]圆方树广义圆方树

    引入 偶尔,我们会遇到一些要在无向图/仙人掌上做的问题,这些问题如果在树上就会比较方便,那么我们就开始考虑能不能把原图等效成一棵树,然后就可以方便地乱搞了? 圆方树就是一种将无向图/仙人掌变成树的数据 ...

  2. 点双联通分量,圆方树和广义圆方树

    点双联通分量 边双联通分量想必看这篇博客的同学就会,并且边双联通分量理解和打起来比较简单,就不再赘述了. 点双联通分量,类比边双的定义,它是原图的极大无向子图,满足删去子图中任意一个节点以及与其相邻的 ...

  3. 道路相遇【一般图的圆方树-广义圆方树】

    题目链接 刚开始拿到这道题的时候,先写了Tarjan缩点构树,没过样例,但是先把40分拿到了. 然后再想,就如同样例给出的那样,我们所定义的原点和方点,实际上在Tarjan直接缩点上并不能起到直接体现 ...

  4. BZOJ3331 [BeiJing2013]压力 广义圆方树

    3331: [BeiJing2013]压力 Description 如今,路由器和交换机构建起了互联网的骨架.处在互联网的骨干位置的核心路由器典型的要处理100Gbit/s的网络流量.他们每天都生活在 ...

  5. Fantasia 【HDU - 5739】【广义圆方树】

    题目链接 这道题的题意在这里就不展开了,因为这次的英文比较的好读,也没有生词,好懂一些些hh. 然后,这道题的关键点,肯定就是来看这个点是不是一个割点,也就是割去这个点之后就将原来的联通块展开成两个以 ...

  6. Codeforces Round #628 (Div. 2) F. Ehab‘s Last Theorem dfs树

    传送门 文章目录 题意: 思路: 题意: 给你个nnn个点mmm条边的图,可以选择完成以下两个任务中的一个: (1)(1)(1)找出大小恰好为n\sqrt nn​的一个独立集. (2)(2)(2)找出 ...

  7. Codeforces Round #740 (Div. 2) F. Top-Notch Insertions 线段树 / 平衡树 + 组合数学

    传送门 文章目录 题意: 思路: 题意: 思路: 考虑最终的序列是什么鸭子的,首先序列肯定单调不降,也就是a1≤a2≤a3≤...≤ana_1\le a_2\le a_3\le ...\le a_na ...

  8. Codeforces Round #453 (Div. 1) D. Weighting a Tree 构造 + dfs树

    传送门 文章目录 题意: 思路: 题意: 给你一颗nnn个点的图,每个点都有一个点权cic_ici​,要求你给每个边赋一个权值kik_iki​,要求对于每个点与他相连的边的权值之和等于这个点的点权ci ...

  9. Codeforces Round #675 (Div. 2) F. Boring Queries 区间lcm + 主席树

    传送门 文章目录 题意: 思路: 题意: 给你一个长度为nnn的序列aaa,qqq个询问,每次询问[l,r][l,r][l,r]内的lcmlcmlcm是多少,对1e9+71e9+71e9+7取模. n ...

最新文章

  1. 为什么一定要杀掉病毒?---帮一位老师解决MyDocument.exe优盘文件夹图标病毒问题...
  2. Meta旨在打造世界上最快的人工智能超级计算机
  3. socket的半包,粘包与分包的问题
  4. 网络服务器费信息技术服务费,中山大学网络与信息技术中心网费在线系统
  5. 清新淡雅水彩手绘花卉插画素材,psd分层好用!
  6. win7 64 php5ts.dll,windows7 64位 php5.3安装php_mongo.dll方法
  7. utilities——C++常用仿函数(二)
  8. 多选框勾选 和 后台数据处理
  9. Android -- 闹钟服务的使用(单次闹钟)
  10. ArcGIS利用DEM提取河流水系(附练习数据下载)
  11. 中学计算机课小课题,中学信息技术课题题目
  12. systemctl开机启动设置
  13. DevExpress v18.2版本亮点——Reporting篇(三)
  14. 解决vue和vue-template-compiler版本不一致问题
  15. 眼动数据分析基础_02
  16. 安装青龙面板开启京东白嫖模式
  17. 篮球数据API接口 - 【篮球文字直播】API调用示例代码
  18. 在python中创建一个具有特定大小的空列表
  19. linux杀死线程函数,Linux线程-pthread_kill
  20. 腾讯可视化, 低代码生成器,正式开源!

热门文章

  1. python自学书-大牛推荐的10本学习 Python 的好书
  2. 2018年python工作好找吗-2018年IT行业薪资大揭秘:你拖后腿了吗?
  3. python3哪个版本稳定-python3哪个版本稳定
  4. python是什么课程-python课程体系是怎么样的?
  5. 全球硬科技开发者大会(成都)开幕 蓝光发展等超300名开发者「乘风」数字升级...
  6. 策略模式和工厂模式的区别_设计模式系列 — 策略模式
  7. Express框架的请求处理~非常详细
  8. aes解密设置utf8 php,PHP aes (ecb)解密后乱码问题
  9. python在d盘增加环境变量配置_怎样配置Python环境变量
  10. Filebeat 将多个日志输出到不同的 Kafka Topic