【BZOJ2125】最短路(仙人掌,圆方树)

题面

BZOJ

求仙人掌上两点间的最短路

题解

终于要构建圆方树啦

首先构建出圆方树,因为是仙人掌,和一般图可以稍微的不一样

直接\(tarjan\)缩点,对于每一个强连通分量构建方点(只有一个点的就不要建了)

圆方边的权值定义为到\(dfs\)(\(Tarjan\)不就是搞了一棵\(dfs\)树出来吗?)树上深度最小的点的最短距离。

为什么会有最短距离?因为它是一个环啊,走两侧的距离是不同的。

将圆方树树链剖分,和普通的求距离一样,先求解\(LCA\)

如果\(LCA\)是圆点,那么和普通的树没有任何区别,直接求解

如果是方点,那么意味这这两个点的祖先在一个环上

因此,最短路要考虑这个环上这两个祖先的较小距离

对于方点维护一下环的长度,记录一下每个点到达深度最小的点是否经过返祖边

求距离时,首先跳到这两个环上的点,然后计算一下距离就好啦。

怎么跳到环上?

方案一:不用树链剖分了,我直接用倍增

方案二:考虑树链剖分每个点只有一个重儿子,现在要求的是当前这个点到达\(LCA\)的所有祖先中,是\(LCA\)儿子的那个点。

我们分类讨论一下,如果它是重儿子,那就是\(LCA\)的\(dfs\)序的后面那个点。

如果不是重儿子,那么它就是一条重链的起点,并且他的父亲是\(LCA\)。

既然这样,沿着重链跳就好啦

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 20000
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Line{int v,next,w;};
struct Link
{
Line e[111111];
int h[MAX],cnt;
inline void Add(int u,int v,int w)
{
e[++cnt]=(Line){v,h[u],w};h[u]=cnt;
e[++cnt]=(Line){u,h[v],w};h[v]=cnt;
}
}T,G;
int n;
struct RST
{
int fa[MAX],size[MAX],hson[MAX],top[MAX],dep[MAX],dis[MAX];
int dfn[MAX],tim,ln[MAX],cir[MAX];
bool zn[MAX];
void dfs1(int u,int ff)
{
fa[u]=ff;size[u]=1;dep[u]=dep[ff]+1;
for(int i=T.h[u];i;i=T.e[i].next)
{
int v=T.e[i].v;if(v==ff)continue;
dis[v]=dis[u]+T.e[i].w;
dfs1(v,u);size[u]+=size[v];
if(size[v]>size[hson[u]])hson[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp;dfn[u]=++tim,ln[tim]=u;
if(hson[u])dfs2(hson[u],tp);
for(int i=T.h[u];i;i=T.e[i].next)
if(T.e[i].v!=fa[u]&&T.e[i].v!=hson[u])
dfs2(T.e[i].v,T.e[i].v);
}
int LCA(int u,int v)
{
while(top[u]^top[v])dep[top[u]]<dep[top[v]]?v=fa[top[v]]:u=fa[top[u]];
return dep[u]<dep[v]?u:v;
}
int Jump(int u,int LCA)
{
int ret;
while(top[u]!=top[LCA])
ret=top[u],u=fa[top[u]];
return u==LCA?ret:ln[dfn[LCA]+1];
}
int Query(int u,int v)
{
int lca=LCA(u,v);
if(lca<=n)return dis[u]+dis[v]-2*dis[lca];
int uu=Jump(u,lca),vv=Jump(v,lca);
int d1=dis[uu]-dis[lca],d2=dis[vv]-dis[lca];
if(!zn[uu])d1=cir[lca]-d1;if(!zn[vv])d2=cir[lca]-d2;
return dis[u]-dis[uu]+dis[v]-dis[vv]+min(abs(d1-d2),cir[lca]-abs(d1-d2));
}
}RST;
int dfn[MAX],low[MAX],tim,tp[MAX],dep[MAX];
int fa[MAX];
ll dis[MAX];
int S[MAX],tot,m,Q;
void Build(int u,int y,int d)
{
int top=dep[y]-dep[u]+1,sum=d,Dis=0;
for(int i=y;i!=u;i=fa[i])S[top--]=i,sum+=dis[i]-dis[fa[i]];
++tot;S[1]=u;top=dep[y]-dep[u]+1;RST.cir[tot]=sum;
for(int i=1;i<=top;++i)
{
int D=min(Dis,sum-Dis);
T.Add(tot,S[i],D);
RST.zn[S[i]]=(D==Dis);
Dis+=dis[S[i+1]]-dis[S[i]];
}
}
void Tarjan(int u,int ff)
{
dfn[u]=low[u]=++tim;dep[u]=dep[ff]+1;fa[u]=ff;
for(int i=G.h[u];i;i=G.e[i].next)
{
int v=G.e[i].v;if(v==ff)continue;
if(!dfn[v])
{
dis[v]=dis[u]+G.e[i].w;
Tarjan(v,u);low[u]=min(low[u],low[v]);
}
else low[u]=min(low[u],dfn[v]);
if(dfn[u]<low[v])T.Add(u,v,G.e[i].w);
}
for(int i=G.h[u];i;i=G.e[i].next)
{
int v=G.e[i].v;if(v==ff)continue;
if(fa[v]!=u&&dfn[u]<dfn[v])Build(u,v,G.e[i].w);
}
}
int main()
{
tot=n=read();m=read();Q=read();G.cnt=1;
for(int i=1;i<=m;++i)
{
int u=read(),v=read(),w=read();
G.Add(u,v,w);
}
Tarjan(1,0);
RST.dfs1(1,0);RST.dfs2(1,1);
while(Q--)printf("%d\n",RST.Query(read(),read()));
return 0;
}

【BZOJ2125】最短路(仙人掌,圆方树)的更多相关文章

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

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

  2. BZOJ.2125.最短路(仙人掌 圆方树)

    题目链接 圆方树.做题思路不写了.. 就是当LCA是方点时跳进那个环可以分类讨论一下用树剖而不必须用倍增: 如果v是u的(唯一的那个)重儿子,那么u的DFS序上+1的点即是要找的:否则v会引出一条新的 ...

  3. 仙人掌&圆方树学习笔记

    仙人掌&圆方树学习笔记 1.仙人掌 圆方树用来干啥? --处理仙人掌的问题. 仙人掌是啥? (图片来自于\(BZOJ1023\)) --也就是任意一条边只会出现在一个环里面. 当然,如果你的图 ...

  4. 仙人掌 && 圆方树 && 虚树 总结

    仙人掌 && 圆方树 && 虚树 总结 Part1 仙人掌 定义 仙人掌是满足以下两个限制的图: 图完全联通. 不存在一条边处在两个环中. 其中第二个限制让仙人掌的题做 ...

  5. 仙人掌&圆方树

    仙人掌&圆方树 Tags:图论 [x] [luogu4320]道路相遇 https://www.luogu.org/problemnew/show/P4320 [ ] [SDOI2018]战略 ...

  6. UOJ.87.mx的仙人掌(圆方树 虚树)(未AC)

    题目链接 本代码10分(感觉速度还行..). 建圆方树,预处理一些东西.对询问建虚树. 对于虚树上的圆点直接做:对于方点特判,枚举其所有儿子,如果子节点不在该方点代表的环中,跳到那个点并更新其val, ...

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

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

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

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

  9. [BZOJ4316]小C的独立集(圆方树DP)

    题意:求仙人掌图直径. 算法:建出仙人掌圆方树,对于圆点直接做普通的树上DP(忽略方点儿子),方点做环上DP并将值直接赋给父亲. 建图时有一个很好的性质,就是一个方点在邻接表里的点的顺序正好就是从环的 ...

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

    仙人掌 圆方树是用来解决仙人掌图的问题的,那什么是仙人掌图呢? 如图,不存在边同时属于多个环的无向连通图是一棵仙人掌 圆方树 定义 原先的仙人掌图,通过一些奇妙的方法,可以转化为一棵由圆点,方点和树边 ...

随机推荐

  1. CentOS 6.5 手动rpm包安装gcc、g++

    摘自:https://blog.csdn.net/lichen_net/article/details/70211204 mount CentOS的安装光盘,然后先后安装 rpm -ivh ppl-0 ...

  2. 线程中的current thread not owner异常错误

    多线程常用的一些方法: wait(),wait(long),notify(),notifyAll()等 这些方法是当前类的实例方法, wait()      是使持有对象锁的线程释放锁;wait(lo ...

  3. python-边练边学

    #换行print(a),print(b),print(c)'''以上是不换行打印以下是换行打印'''print(a)print(b)print(c) #注释#python中的注释有三种方式:单行注释 ...

  4. Display Hibernate SQL to console – show_sql , format_sql and use_sql_comments

    (转)灵活控制 Hibernate 的日志或 SQL 输出,以便于诊断 - CS408 - 博客园 https://www.cnblogs.com/lixuwu/p/7479496.html Disp ...

  5. WCF使用相关

    1.不显示WCF服务主机 在WCF项目属性中的WCF选项卡总关闭下图的选项 2.在其他项目中承载WCF服务 其他加载的操作一致,需要把WCF的endpoint和behavior节点复制到 启动服务的那 ...

  6. SSH上传/下载本地文件到linux服务器

    在linux下一般用scp这个命令来通过ssh传输文件. 1.从服务器上下载文件 scp username@servername:/path/filename /var/www/local_dir(本 ...

  7. postgreSQL使用杂谈

    由于当时是在美国安装的postgreSQL ,导致回到上海后使用时,发现时间数据显示不正确. To acomplish the timezone change in Postgres 9.6 you ...

  8. 随机森林(Random Forest)

    阅读目录 1 什么是随机森林? 2 随机森林的特点 3 随机森林的相关基础知识 4 随机森林的生成 5 袋外错误率(oob error) 6 随机森林工作原理解释的一个简单例子 7 随机森林的Pyth ...

  9. systemd取消对服务重启的限制

    默认情况下,一个服务在10秒内最多允许启动5次.当超过5次后,会报如下错误: Job for xx.service failed because start of the service was at ...

  10. Armstrong公理

    从已知的一些函数依赖,可以推导出另外一些函数依赖,这就需要一系列推理规则,这些规则常被称作“Armstrong 公理”. 设U 是关系模式R 的属性集,F 是R 上成立的只涉及U 中属性的函数依赖集. ...