当前位置: 首页 > news >正文

【BZOJ2125】—最短路(圆方树+树链剖分)

传送门

题意:询问仙人掌上2点之间最短路

先建出圆方树,每个圆点到方点的距离为到这个环最高点的最短距离
每次询问分类讨论一下圆点方点
如果是方点的话找到到这个环的那个入点,计算2个入点之间最短距离就可以了

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<18|1;
#define file freopen("lx.cpp","r",stdin);
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0,f=0;
    while(!isdigit(ch))f^=(ch=='-'),ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?-res:res;
}
const int N=40004;
struct Graph{
    int cnt,adj[N],nxt[N<<1],to[N<<1],val[N<<1];
    inline void add(int u,int v,int w){
        nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,val[cnt]=w;
    }
    inline void addedge(int u,int v,int w){
        add(u,v,w),add(v,u,w);
    }
}G,T;
int n,m,q;
int dfn[N],fa[N],dep[N],bel,plc[N],dis[N],low[N],stk[N],tot,len[N];
inline void buildRec(int u,int v,int w){
    int top=dep[v]-dep[u]+1,sum=w,dt=0;
    for(int i=v;i!=u;i=fa[i])stk[top--]=i,sum+=dis[i]-dis[fa[i]];
    bel++,len[bel]=sum,stk[1]=u;
    for(int i=1;i<=dep[v]-dep[u]+1;i++){
        int d=min(dt,sum-dt);
        T.addedge(bel,stk[i],d);
        plc[stk[i]]=d==dt;
        dt+=dis[stk[i+1]]-dis[stk[i]];
    }
}
void tarjan(int u){
    dfn[u]=low[u]=++tot;
    for(int e=G.adj[u];e;e=G.nxt[e]){
        int v=G.to[e];
        if(v==fa[u])continue;
        if(!dfn[v]){
            fa[v]=u,dep[v]=dep[u]+1,dis[v]=dis[u]+G.val[e];
            tarjan(v),low[u]=min(low[u],low[v]);
        }
        else low[u]=min(low[u],dfn[v]);
        if(dfn[u]<low[v])T.addedge(u,v,G.val[e]);
    }
    for(int e=G.adj[u];e;e=G.nxt[e]){
        int v=G.to[e];
        if(v==fa[u])continue;
        if(fa[v]!=u&&dfn[u]<dfn[v])buildRec(u,v,G.val[e]);
    }
}
namespace SLPF{
    int pos[N],idx[N],siz[N],son[N],dis[N],fa[N],top[N],dep[N],tot;
    void dfs1(int u){
        siz[u]=1;
        for(int e=T.adj[u];e;e=T.nxt[e]){
            int v=T.to[e];
            if(v==fa[u])continue;
            dep[v]=dep[u]+1,fa[v]=u,dis[v]=dis[u]+T.val[e];
            dfs1(v),siz[u]+=siz[v];
            if(siz[u]>siz[son[u]])son[u]=v;
        }
    }
    void dfs2(int u,int tp){
        pos[u]=++tot,idx[tot]=u,top[u]=tp;
        if(son[u])dfs2(son[u],tp);
        for(int e=T.adj[u];e;e=T.nxt[e]){
            int v=T.to[e];
            if(v==fa[u]||v==son[u])continue;
            dfs2(v,v);
        }
    }
    inline int Lca(int u,int v){
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])swap(u,v);
            u=fa[top[u]];
        }return dep[u]>dep[v]?v:u;
    }
    inline int jump(int u,int g){
        int pre;
        while(top[u]!=top[g]){
            pre=top[u],u=fa[top[u]];
        }
        return u==g?pre:idx[pos[g]+1];
    }
    inline int query(int u,int v){
        int lca=Lca(u,v);
        if(lca<=n)return dis[u]+dis[v]-2*dis[lca];
        int sonu=jump(u,lca),sonv=jump(v,lca);
        int du=dis[sonu]-dis[lca],dv=dis[sonv]-dis[lca];
        if(plc[sonu])du=len[lca]-du;if(plc[sonv])dv=len[lca]-dv;
        if(du<dv)swap(du,dv);
        return min(du-dv,len[lca]-du+dv)+dis[u]-dis[sonu]+dis[v]-dis[sonv];
    }
}
int main(){
    //file;
    bel=n=read(),m=read(),q=read();
    for(int i=1;i<=m;i++){
        int u=read(),v=read(),w=read();
        G.addedge(u,v,w);
    }
    tarjan(1);
    SLPF::dfs1(1),SLPF::dfs2(1,1);
    while(q--){
        int u=read(),v=read();
        cout<<SLPF::query(u,v)<<'\n';
    }
}

转载于:https://www.cnblogs.com/stargazer-cyk/p/11145579.html

相关文章:

  • Java学习笔记-正则表达式
  • centos7.5搭建zabbix3.4.x以及mysql定制化监控
  • java ReentrantLock
  • C学习笔记-makefile
  • cocos2dx笔记1:概述
  • 易语言QQpost加好友源码
  • Ansible-----常用功能
  • 2019春第六周学习编辑总结
  • 【感悟】一次不太好的寻找bug的体验,RecyclerView
  • mysql 命令启动
  • [题解]区间dp_luogu_P3147 262144
  • Permission denied: .gvfs
  • day2
  • JSP语法入门
  • 学习备忘英语单词转载
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • Android Volley源码解析
  • ComponentOne 2017 V2版本正式发布
  • css属性的继承、初识值、计算值、当前值、应用值
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • in typeof instanceof ===这些运算符有什么作用
  • Koa2 之文件上传下载
  • leetcode46 Permutation 排列组合
  • Linux链接文件
  • maya建模与骨骼动画快速实现人工鱼
  • Mysql数据库的条件查询语句
  • React-redux的原理以及使用
  • Service Worker
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 程序员该如何有效的找工作?
  • 给初学者:JavaScript 中数组操作注意点
  • 面试题:给你个id,去拿到name,多叉树遍历
  • 前嗅ForeSpider采集配置界面介绍
  • 为视图添加丝滑的水波纹
  • 新书推荐|Windows黑客编程技术详解
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • Python 之网络式编程
  • 进程与线程(三)——进程/线程间通信
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • !!Dom4j 学习笔记
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • $$$$GB2312-80区位编码表$$$$
  • (C#)一个最简单的链表类
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (Python) SOAP Web Service (HTTP POST)
  • (超详细)语音信号处理之特征提取
  • (二)正点原子I.MX6ULL u-boot移植
  • (分类)KNN算法- 参数调优
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • .mysql secret在哪_MYSQL基本操作(上)