无向仙人掌图 一般需要重构成 仙人掌有向树
然后我们 就考虑 圆点的 方点的不同讨论

这个题是查询两点间最短路
如果lca 是圆点 那么就是 d[a]+d[b]-2*d[lca]
如果是方点 我们需要 考虑在环上的 的两个点的 的最短距离有两种情况
取min 然后 再加上 另外两段 (len1 len2)
这里使用的的是倍增求lca
如果树剖求的话可能有些麻烦

我看了很多博客 我这种是y总写法的改进
他用的是边双 连通分量建立边
但是本题中是可以按照有向图去考虑问题的

            int len1 = dis[a] - dis[A];int len2 = dis[b] - dis[B];int len3 = abs(s[A] - s[B]);len3 = min(len3, s[p] - len3);
#include <bits/stdc++.h>
using namespace  std;
//#define  int long long
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
#define fi first
#define se second
#define pb  push_back
#define inf 1ll<<62
#define endl "\n"
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define de_bug(x) cerr << #x << "=" << x << endl
#define all(a) a.begin(),a.end()
#define IOS   std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define  fer(i,a,b)  for(int i=a;i<=b;i++)
#define  der(i,a,b)  for(int i=a;i>=b;i--)
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
const int M = N * 3;
int n, m, q, nee;
int h1[N], h2[N], e[M], w[M], ne[M], idx;
int dfn[N], low[N], cnt;
int s[N], f[N], b[N];
int fa[N][16];
int dis[N];
int d[N];
int A, B;
void add(int h[], int a, int b, int c) {e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
void build(int x, int y, int z) {int sum = z;int t = y;while(t != x) {s[t] = sum;sum += b[t];t = f[t];}s[x] = sum;s[++nee] = sum;add(h2, x, nee, 0);t = y;while (t != x) {add(h2, nee, t, min(s[t], sum - s[t]));t = f[t];}
}
void tarjan(int u, int from) {dfn[u] = low[u] = ++ cnt;for (int i = h1[u]; ~i; i = ne[i]) {int j = e[i];int ff = 1;if(j == from && ff == 1) {continue;ff = 0;}if (!dfn[j]) {f[j] = u;b[j] = w[i];tarjan(j, u);}low[u] = min(low[u], low[j]);if (dfn[u] < low[j]) add(h2, u, j, w[i]);}for (int i = h1[u]; ~i; i = ne[i]) {int j = e[i];if (dfn[u] < dfn[j] && f[j] != u)build(u, j, w[i]);}
}
void dfs(int u, int ff) {d[u] = d[ff] + 1;fa[u][0] = ff;for(int i = 1; i <= 15; i++)fa[u][i] = fa[fa[u][i - 1]][i - 1];for(int i = h2[u]; ~i; i = ne[i]) {int v = e[i];dis[v] = dis[u] + w[i];dfs(v, u);}
}
int lca(int a, int b) {if(d[a] < d[b])swap(a, b);for(int i = 15; i >= 0; i--) {if(d[fa[a][i]] >= d[b])a = fa[a][i];}if(a == b)return a;for(int i = 15; i >= 0; i--) {if(fa[a][i] != fa[b][i]) {a = fa[a][i];b = fa[b][i];}}A = a;B = b;return fa[a][0];
}
void solve() {cin >> n >> m >> q;nee = n;memset(h1, -1, sizeof h1);memset(h2, -1, sizeof h2);while (m -- ) {int a, b, c;cin >> a >> b >> c;add(h1, a, b, c), add(h1, b, a, c);}tarjan(1, -1);dfs(1, 0);while (q -- ) {int a, b;cin >> a >> b;int p = lca(a, b);if (p <= n) cout << dis[a] + dis[b] - dis[p] * 2 << endl;else {int len1 = dis[a] - dis[A];int len2 = dis[b] - dis[B];int len3 = abs(s[A] - s[B]);len3 = min(len3, s[p] - len3);cout << len1 + len2 + len3 << endl;}}
}
int main() {IOS;int _ = 1;//cin>>_;while( _-- )solve();return 0;
}
```cpp
广义圆方树 建图
void tarjan (int x, int fa) {low[x] = dfn[x] = ++idx;s.push(x);for(auto v : g[x]) {if(!dfn[v]) {tarjan(v,x);low[x] = min(low[x], low[v]);if(low[v] >= dfn[x]) {++cnt;e[cnt].push_back(x);int t;while(1) {t = s.top();s.pop();e[cnt].push_back(t);if(t == v)break;}}} else if(v != fa) low[x] = min(low[x], dfn[v]);}
}

P5236 【模板】静态仙人掌(仙人掌圆方树)相关推荐

  1. 洛谷 :P5236 【模板】静态仙人掌(圆方树模板 + 仙人掌最短路)

    题意很简单,在仙人掌图上求两点的最短路. 做法:需要用到圆方树 先来看看什么是圆方树:圆方树,就是由仙人掌图转化而来,树上分两种点:圆点和方点,圆点是仙人掌图上的点,方点是由仙人掌的环转化而来. 由于 ...

  2. 仙人掌与圆方树的学习 【模板】静态仙人掌

    题目链接 BZOJ 2125 最短路 圆方树 求一幅仙人掌图中,Q次询问两点最短路. 仙人掌问题,我们可以直接将原来的N个点缩点成为一棵生成树--圆方树. 这棵圆方树是怎样建立的呢,首先,我们看图: ...

  3. bzoj4564: [Haoi2016]地图 仙人掌的圆方树 莫队 分块

    bzoj4564: [Haoi2016]地图 Description 一天rin来到了一个遥远的都市.这个都市有n个建筑,编号从1到n,其中市中心编号为1,这个都市有m条双向通 行的街道,每条街道连接 ...

  4. 仙人掌相关问题的解法(1)-DFS树解决仙人掌DP问题,圆方树

    前言 有难度的仙人掌题在近几年也只是在国家集训队水平的比赛里才会出现. 不过,这不是说仙人掌对国集水平以下的选手意义不大: 首先,仙人掌暴力 DP 问题难度并不大,在省选. NOI 甚至 NOIP 中 ...

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

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

  6. [XSY] 绿色(圆方树、树形DP、树上差分)

    绿色 题意简述 题解 首先,每次修改完点权后,重新考虑一遍所有路径显然是不现实的,所以我们考虑求出经过每个点的两端同色的简单路径数,这样权值和容易统计和修改. 接下来分析仙人掌上的简单路径性质.一条简 ...

  7. 仙人掌圆方树学习笔记

    终于对仙人掌有了一点初步的理解. 仙人掌 仙人掌是什么? 仙人掌是一个无向图. 仙人掌有什么特点? 仙人掌的每条边只属于一个简单环. 下面是一个栗子 有什么用呢? 我们可以先用\(tarjan\)找出 ...

  8. 仙人掌问题(圆方树)

    [算法简介] 仙人掌就是把树上多连了一些返祖边,构成了一些环 根据仙人掌这个名字我们也可以较为形象的感受到图的形态 具体的,仙人掌分为点仙人掌和边仙人掌,定义分别为点/边最多属于一个环 之所以把这样的 ...

  9. cactus仙人掌图【仙人掌圆方树+树形DP+单调队列】

    题目链接 BZOJ 1023 首先,圆方树是比较好想到的,维护直径,我们最方便的做法就是先让它变成一棵树,这里因为是仙人掌图,所以就用圆方树来构建. 再者,就是维护直径了,比较好想到的是非环上结点,就 ...

最新文章

  1. 1.2机器学习基础下--python深度机器学习
  2. HDFS数据的写入过程
  3. 李牛(Linux)vi
  4. 关于索爱MT15i连接win7——MTP USB驱动无法安装
  5. 怎样在matlab q-q图上读出斜率,Q分解法潮流计算matlab小程序
  6. 【MyBatis笔记】08-输出类型
  7. c++游戏开发案例源代码_1人开发千万下载,爆款游戏TENKYU调优案例
  8. win7新建文件夹-快捷键
  9. Linux 分区简介
  10. 喇叭正反相位测试音频_音频功放失真的四大要点及改善方法
  11. 整数规划的matlab计算,Matlab遗传算法解决整数规划问题
  12. MaxScript 加密脚本 ms to mse
  13. 2013年4月小游戏行业网站综合影响力排名
  14. 什么是PECL电平以及常用的匹配电路
  15. 短视频直播系统的功能
  16. 苹果硬改手机底层udid无限新机技术
  17. vue实现店铺装修h5用户端实现
  18. 在xp系统电脑上建立宽带连接服务器吗,windows 7与windows xp创建宽带连接的方法-电脑教程...
  19. 一行命令 Ping 网段所有 IP
  20. 马士兵老师的多线程高并发笔记

热门文章

  1. 区块链挑战传统支付体系
  2. 带你去看《一支铅笔诞生的世界-世界经典动漫原画展》
  3. 《C陷阱与缺陷》——第三章(语义陷阱)
  4. 转载 PCIe学习(二):PCIe DMA关键模块分析之一
  5. kettle案例4.1.1--抽取文本数据---TSV文件的抽取
  6. 判断文件或目录是否存在的几种方式
  7. ODBC驱动的官网下载地址
  8. cocos2dx 背包界面的实现
  9. Zemax操作--4(公差问题)
  10. c++语言字母转换,c++大小写字母转换的思路有几种?