description

给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径。


analysis

  • 建出圆方树后,可以知道仙人掌上每一个方点连着的边双其实就是一个简单环

  • \(tarjan\)缩环的时候可以先弄出每个环的边权和并做一个前缀和,这样环中两点距离就可求

  • 设\(dis[i]\)表示从根节点到\(i\)节点的最小值,若\(x,y\)两点\(LCA\)是原点,则可以直接求

  • 若为方点则表示\(x,y\)距离\(LCA\)最近的祖先是环上不相邻两点,只需要再判断环上这两点最短距离即可


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<map>
#define MAXN 100005
#define MAXM 200005
#define ll long long
#define reg register ll
#define max(x,y) ((x>y)?(x):(y))
#define min(x,y) ((x<y)?(x):(y))
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define rep(i,a) for (reg i=las[a];i;i=nex[i]) using namespace std; ll anc[MAXN][16];
ll las[MAXM],nex[MAXM],tov[MAXM],len[MAXM];
ll dfn[MAXN],low[MAXN],stack[MAXN];
ll fa[MAXN],sum[MAXN],dep[MAXN],dis[MAXN],size[MAXN];
ll n,m,q,nn,tot,tot1,num,top;
map<ll,ll>mp[MAXN],c[MAXN];
vector<ll>v[MAXN]; inline ll read()
{
ll x=0,f=1;char ch=getchar();
while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline void link(ll x,ll y,ll z){nex[++tot]=las[x],las[x]=tot,tov[tot]=y,len[tot]=z;}
inline void tarjan(ll x)
{
dfn[x]=low[x]=++tot,stack[++top]=x;
rep(i,x)if (!dfn[tov[i]])
{
tarjan(tov[i]),low[x]=min(low[x],low[tov[i]]);
if (low[tov[i]]>=dfn[x])
{
ll tmp=0,last=0;++n;
while (tmp!=tov[i])
{
last=tmp,tmp=stack[top--];
v[n].push_back(tmp),v[tmp].push_back(n); size[n]+=last==0?mp[tmp][x]:mp[tmp][last];
c[n][tmp]=size[n];
}
v[n].push_back(x),v[x].push_back(n);
size[n]+=mp[x][tmp],c[n][x]=size[n];
}
}
else low[x]=min(low[x],dfn[tov[i]]);
}
inline ll query(ll pos,ll x,ll y)
{
ll tmp=abs(c[pos][x]-c[pos][y]);
return min(tmp,size[pos]-tmp);
}
inline void dfs(ll x,ll y)
{
anc[x][0]=y,dep[x]=dep[y]+1;
fo(i,1,15)anc[x][i]=anc[anc[x][i-1]][i-1];
if (x<=nn)
{
ll ff=anc[y][0];
dis[x]=x==1?0:dis[ff]+query(y,x,ff);
}
fo(i,0,v[x].size()-1)if (v[x][i]!=y)dfs(v[x][i],x);
}
inline ll lca(ll x,ll y)
{
if (dep[x]<dep[y])swap(x,y);
fd(i,15,0)if (dep[anc[x][i]]>=dep[y])x=anc[x][i];
if (x==y)return x;
fd(i,15,0)if (anc[x][i]!=anc[y][i])x=anc[x][i],y=anc[y][i];
return anc[x][0];
}
inline ll get(ll x,ll y,ll z)
{
ll ans=dis[x]+dis[y];
fd(i,15,0)
{
if (dep[anc[x][i]]>dep[z])x=anc[x][i];
if (dep[anc[y][i]]>dep[z])y=anc[y][i];
}
return ans-dis[x]-dis[y]+query(z,x,y);
}
int main()
{
//freopen("T2.in","r",stdin);
//freopen("T2.out","w",stdout);
n=nn=read(),m=read(),q=read();
fo(i,1,m)
{
ll x=read(),y=read(),z=read();
link(x,y,z),link(y,x,z),mp[x][y]=mp[y][x]=z;
}
tarjan(1),dfs(1,0);
while (q--)
{
ll x=read(),y=read(),LCA=lca(x,y);
printf("%lld\n",LCA<=nn?dis[x]+dis[y]-2*dis[LCA]:get(x,y,LCA));
}
return 0;
}

【JZOJ1914】【BZOJ2125】最短路的更多相关文章

  1. [BZOJ2125]最短路(圆方树DP)

    题意:仙人掌图最短路. 算法:圆方树DP,$O(n\log n+Q\log n)$ 首先建出仙人掌圆方树(与点双圆方树的区别在于直接连割边,也就是存在圆圆边),然后考虑点u-v的最短路径,显然就是:在 ...

  2. bzoj2125 最短路

    Description 给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径. Input 输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个 ...

  3. BZOJ2125 最短路 圆方树、倍增

    传送门 对仙人掌建立圆方树,然后对边定权 对于圆点和圆点之间的边,是原来仙人掌上的桥,边权保持不变 对于圆点和方点之间的边,将圆方树看做以一个圆点为根的有根树之后,一个方点的父亲一定是一个圆点.对于这 ...

  4. 2018.07.25 bzoj2125: 最短路(圆方树+倍增)

    传送门 人生的第一道仙人掌. 这道题求是仙人掌上的最短路. 先建出圆方树,然后用倍增跑最短路,当lca" role="presentation" style=" ...

  5. BZOJ2125 最短路 【仙人掌最短路】

    题目 给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径. 输入格式 输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个整数v,u,w表示一 ...

  6. bzoj2125 最短路——仙人掌两点间距离

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2125 仙人掌!模仿 lyd 的代码写的,也算是努力理解了: 主要分成 lca 在环上和不在环 ...

  7. [BZOJ2125]最短路[圆方树]

    题意 给定仙人掌,多次询问两点之间的最短路径. \(n\le 10000, Q\le 10000​\) 分析 建出圆方树,分路径 lca 是圆点还是方点讨论. 预处理出根圆点到每个圆点的最短距离 \( ...

  8. 【题解】Bzoj2125最短路

    处理仙人掌 ---> 首先建立出圆方树.则如果询问的两点 \(lca\) 为圆点,直接计算即可, 若 \(lca\) 为方点,则需要额外判断是走环的哪一侧(此时与两个点在环上的相对位置有关.) ...

  9. bzoj3047:Freda的传呼机&&bzoj2125: 最短路

    完结撒花!!!!!!!!!!! 最后一题填坑1A仙人掌WWWWWWW我真流弊 首先把环拆开,环中每一个点连向环的根,然后搞LCA,答案就是套路的d[x]+d[y]-d[lca]*2 然后就可以发现,其 ...

  10. 图论杂项细节梳理&模板(虚树,圆方树,仙人掌,欧拉路径,还有。。。)

    orzYCB 虚树 %自为风月马前卒巨佬% 用于优化一类树形DP问题. 当状态转移只和树中的某些关键点有关的时候,我们把这些点和它们两两之间的LCA弄出来,以点的祖孙关系连成一棵新的树,这就是虚树. ...

随机推荐

  1. 割点的tarjan算法模板

    基本思路: 朴素的思想是删除每一个点,然后去dfs,这样无疑会爆炸 换一种思路,怎样判断是割点呢,如果是根节点的话毫无疑问只要看子树的数目,但是如果不是根节点呢,不知大牛是怎样想到的 利用两个数组df ...

  2. 新建maven项目index.jsp文件报错处理

    最近用eclipse新建了一个maven项目,结果刚新建完成index.jsp页面就报错了,先把错误信息贴出来看看 后来就找资料,结果发现两种解决办法,希望可以帮助用得上的人! 第一种:直接在pom. ...

  3. NFA 、DFA 简述

    转载请注明出处 https://www.cnblogs.com/majianming/p/11823697.html 目前常见的正则表达引擎总体分为2种,DFA (确定型有穷状态自动机) 和 NFA ...

  4. GA来源分析

    网页中广告素材分为:文字,图片和FLASH三种.针对这三种素材,2种有无参数的情况,新旧版GA收集到的结果为: 提醒:FLASH素材如果不加参数收集不到来源: 具体GA参数如下: 可参考:https: ...

  5. TCP练习

    然后基本的socket编程,用TCP做两个进程互相发消息.C端主动发hello,S端收到后回world. #include <stdio.h> #include <stdlib.h& ...

  6. RzPageControl(pagecontrol)

    实现多标签的动态添加,切换,关闭 使用RzPageControl来实现多标签页使用菜单来打开标签页,通过标签页的caption来判断将标签页是否已经被打开过了.1.创建标签页,并判断是否是已经打开过的 ...

  7. 常用跨域方法总结(2)——CORS

    常用跨域方法总结(2)--CORS 上篇文章介绍了几种常用的跨域方法:常用跨域方法总结,本片为上一篇的补充,对比较重要的Cross Origin Resource Sharing详细介绍. CORS ...

  8. 66、saleforce 的 approval process

    public class TestApproval { public void submitAndProcessApprovalRequest() { // Insert an account Lin ...

  9. Notepad++ 连接 FTP 实现编辑 Linux文件

    下载并安装插件 github 下载 :https://github.com/ashkulz/NppFTP/releases/ 安装过程 将下载后解压的文件夹中的 NppFTP.dll 文件,拷贝到 n ...

  10. 原生Android项目里嵌入Cordova

    Android H5混合开发():原生Android项目里嵌入Cordova 如果安卓项目已经存在了,那么如何使用Cordova做混合开发? 方案1(适用于插件会持续增加或变化的项目): 新建Cord ...