题目

边权均为2的幂次的无向图,求 \(S\) 到 \(T\) 的最短路

\(n,m\leq 10^5\)


分析

最短路直接考虑用 Dijkstra,它需要维护松弛操作和堆,

那么也就是要重载加号和小于号,而数字可以在主席树上维护。

对于小于号,最直接的一种做法就是从高位到低位找到第一个不同数字的位比较大小,

那么就是先在主席树上二分找到这两个数的LCP,然后比较下一位的大小,

LCP可以用哈希来维护,如果 \(base=2,mod=10^9+7\),顺便就可以把答案求出来,那么就是一个 \(\log\) 的。

对于加号,找到从第x位起第一个0,然后把左边的1都变成0,只把那个0的位置变成1,

这个维护区间左端点为开头极长的1也可以做到一个 \(\log\)

再加上堆的时间复杂度就是 \(O(m\log n\log mx+m\log mx)\)


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int mod=1000000007,N=100021; struct node{int y,w,next;}e[N<<1];
int two[N+11],pre[N],n,m,ans,as[N],S,T,rt[N],et=1,st[N],Top,v[N];
int w[N<<6],ls[N<<6],rs[N<<6],len[N<<6],cnt,Cnt; pair<int,int>heap[N<<1];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void build(int &rt,int l,int r){
rt=++cnt;
if (l==r) return;
int mid=(l+r)>>1;
build(ls[rt],l,mid);
build(rs[rt],mid+1,r);
}
bool geq(int fi,int se,int l,int r){
if (w[fi]==w[se]) return 0;
if (l==r) return w[fi]>w[se];
int mid=(l+r)>>1;
if (w[rs[fi]]==w[rs[se]]) return geq(ls[fi],ls[se],l,mid);
else return geq(rs[fi],rs[se],mid+1,r);
}
int zero(int rt,int l,int r,int x,int y){
if (l==x&&r==y){
if (len[rt]==r-l+1) return 0x3f3f3f3f;
else return l+len[rt];
}
int mid=(l+r)>>1;
if (y<=mid) return zero(ls[rt],l,mid,x,y);
else if (x>mid) return zero(rs[rt],mid+1,r,x,y);
else{
int now=zero(ls[rt],l,mid,x,mid);
if (now!=0x3f3f3f3f) return now;
else return zero(rs[rt],mid+1,r,mid+1,y);
}
}
void upd(int &rt,int l,int r,int x){
int trt=++cnt;
ls[trt]=ls[rt],rs[trt]=rs[rt],rt=trt;
if (l==r){
len[rt]=w[rt]=1;
return;
}
int mid=(l+r)>>1;
if (x<=mid) upd(ls[rt],l,mid,x);
else upd(rs[rt],mid+1,r,x);
w[rt]=(w[ls[rt]]+1ll*w[rs[rt]]*two[mid-l+1]%mod)%mod;
if (len[ls[rt]]==mid-l+1) len[rt]=len[ls[rt]]+len[rs[rt]];
else len[rt]=len[ls[rt]];
}
void update(int &rt,int Rt,int l,int r,int x,int y){
if (l==x&&r==y) {rt=Rt; return;}
else{
int trt=++cnt;
ls[trt]=ls[rt],rs[trt]=rs[rt],rt=trt;
}
int mid=(l+r)>>1;
if (y<=mid) update(ls[rt],ls[Rt],l,mid,x,y);
else if (x>mid) update(rs[rt],rs[Rt],mid+1,r,x,y);
else{
update(ls[rt],ls[Rt],l,mid,x,mid);
update(rs[rt],rs[Rt],mid+1,r,mid+1,y);
}
w[rt]=(w[ls[rt]]+1ll*w[rs[rt]]*two[mid-l+1]%mod)%mod;
if (len[ls[rt]]==mid-l+1) len[rt]=len[ls[rt]]+len[rs[rt]];
else len[rt]=len[ls[rt]];
}
void add(int &Rt,int x){
int now=zero(Rt,0,N,x,N);
upd(Rt,0,N,now);
if (x<now) update(Rt,rt[S],0,N,x,now-1);
}
void Pop(){
heap[1]=heap[Cnt--];
for (int x=1;(x<<1)<=Cnt;){
int y=x<<1|1;
if (y>Cnt||geq(heap[y].first,heap[y-1].first,0,N)) --y;
if (geq(heap[x].first,heap[y].first,0,N)) swap(heap[x],heap[y]),x=y;
else break;
}
}
void Push(pair<int,int> x){
heap[++Cnt]=x;
for (int x=Cnt;x>1;x>>=1)
if (geq(heap[x>>1].first,heap[x].first,0,N))
swap(heap[x],heap[x>>1]);
else break;
}
void Dijkstra(int S){
heap[Cnt=1]=make_pair(rt[S],S),build(rt[S],0,N);
while (Cnt){
while (Cnt&&v[heap[1].second]) Pop();
if (!Cnt) return;
int x=heap[1].second; v[x]=1,Pop();
for (int i=as[x],Rt;i;i=e[i].next)
if (!v[e[i].y]){
int CNT=cnt;
add(Rt=rt[x],e[i].w);
if (!rt[e[i].y]||geq(rt[e[i].y],Rt,0,N)){
rt[e[i].y]=Rt,pre[e[i].y]=x;
Push(make_pair(Rt,e[i].y));
}else for (;cnt>CNT;--cnt) w[cnt]=len[cnt]=ls[cnt]=rs[cnt]=0;
}
}
}
int main(){
n=iut(),m=iut(),two[0]=1;
if (n==1) return !printf("0\n1\n1");
for (int i=1;i<=N;++i) two[i]=2ll*two[i-1]%mod;
for (int i=1;i<=m;++i){
int x=iut(),y=iut(),w=iut();
e[++et]=(node){y,w,as[x]},as[x]=et;
e[++et]=(node){x,w,as[y]},as[y]=et;
}
S=iut(),T=iut(),Dijkstra(S);
if (pre[T]){
for (int _T=T;_T;_T=pre[_T]) st[++Top]=_T;
printf("%d\n%d\n",w[rt[T]],Top);
for (int i=Top;i;--i)
printf("%d%c",st[i],i==1?10:32);
}else printf("-1");
return 0;
}

#主席树,Dijkstra,哈希#CF464E The Classic Problem的更多相关文章

  1. 数据结构(主席树):HDU 4729 An Easy Problem for Elfness

    An Easy Problem for Elfness Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (J ...

  2. LCA+主席树 (求树上路径点权第k大)

      SPOJ 10628. Count on a tree (树上第k大,LCA+主席树) 10628. Count on a tree Problem code: COT You are given ...

  3. 51Nod1863 Travel 主席树 最短路 Dijkstra 哈希

    原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1863.html 题目传送门 - 51Nod1863 题意 有 n 个城市,有 m 条双向路径连通它们 ...

  4. 【CF464E】The Classic Problem(主席树+最短路)

    点此看题面 大致题意: 给你一张无向图,每条边的边权为\(2^{x_i}\),求\(s\)到\(t\)的最短路. 最短路 最短路,首先考虑\(Dijkstra\).这里用\(SPFA\)似乎不太好,因 ...

  5. Codeforces 464E The Classic Problem(主席树+最短路+哈希,神仙题)

    题目链接 题意:给出一张 \(n\) 个点 \(m\) 条边的无向图,第 \(i\) 条边连接 \(u_i,v_i\),边权为 \(2^{w_i}\),求 \(s\) 到 \(t\) 的最短路. \( ...

  6. Codeforces 464E #265 (Div. 1) E. The Classic Problem 主席树+Hash

    E. The Classic Problem http://codeforces.com/problemset/problem/464/E 题意:给你一张无向带权图,求S-T的最短路,并输出路径.边权 ...

  7. BZOJ_3207_花神的嘲讽计划Ⅰ_哈希+主席树

    BZOJ_3207_花神的嘲讽计划Ⅰ_哈希+主席树 Description 背景 花神是神,一大癖好就是嘲讽大J,举例如下: “哎你傻不傻的![hqz:大笨J]” “这道题又被J屎过了!!” “J这程 ...

  8. CodeForces 464E The Classic Problem | 呆克斯歘 主席树维护高精度

    题意描述 有一个\(n\)点\(m\)边的无向图,第\(i\)条边的边权是\(2^{a_i}\).求点\(s\)到点\(t\)的最短路长度(对\(10^9 + 7\)取模). 题解 思路很简单--用主 ...

  9. Codeforces 464E The Classic Problem (最短路 + 主席树 + hash)

    题意及思路 这个题加深了我对主席树的理解,是个好题.每次更新某个点的距离时,是以之前对这个点的插入操作形成的线段树为基础,在O(logn)的时间中造出了一颗新的线段树,相比直接创建n颗线段树更省时间. ...

  10. bzoj 1901: Zju2112 Dynamic Rankings -- 主席树,树状数组,哈希

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MB Description 给定一个含有n个数的序列a[1] ...

随机推荐

  1. win32-LPCSTR->String

    #include <string> void makebox(LPCSTR name) { std::string res(name); res += " is X"; ...

  2. 2024-02-24:用go语言,给你一个 n 个点的带权无向连通图,节点编号为 0 到 n-1, 同时还有一个数组 edges ,其中 edges[i] = [fromi, toi, weighti

    2024-02-24:用go语言,给你一个 n 个点的带权无向连通图,节点编号为 0 到 n-1, 同时还有一个数组 edges ,其中 edges[i] = [fromi, toi, weighti ...

  3. mysql进阶语句优化---day40

    # ###part1: sql语句优化 #(1) mysql 执行流程 客户端: 发送连接请求,然后发送增删改查sql语句进行执行 服务端: 1.连接层:提供和客户端连接的服务,在tcp协议下 提供多 ...

  4. 【华为机试ACM基础#02】从单向链表中删除指定值的节点、输出单向链表中倒数第k个节点(熟悉链表的输入方式)

    从单向链表中删除指定值的节点 输入一个单向链表和一个节点的值,从单向链表中删除等于该值的节点,删除后如果链表中无节点则返回空指针. 链表的值不能重复. 构造过程,例如输入一行数据为: 6 2 1 2 ...

  5. DataGear 制作全国和省级地图联动的数据可视化看板

    DataGear看板的图表联动功能,使您可以轻松制作支持图表联动的全国地图.省级地图数据可视化看板. 首先,新建两个数据集. 第一个是各省指标数据集,将用于绘制全国指标图表,它的SQL语句如下所示: ...

  6. Centos下git pull免密码操作

    在终端输入以下指令: git config --global credential.helper store然后再次执行pull操作,还是会提示一次输入帐号与密码.断开终端链接,重连,再次进行pull ...

  7. 第18章_MySQL8其它新特性

    # 目录: https://www.cnblogs.com/xjwhaha/p/15844178.html 1. MySQL8新特性概述 MySQL从5.7版本直接跳跃发布了8.0版本,可见这是一个令 ...

  8. 32位数字电位器AD5228使用及调试总结

    一 概念 什么是数字电位计? 数字电位器(Digital Potentiometer)亦称数控可编程电阻器,是一种代替传统机械电位器(模拟电位器)的新型CMOS数字.模拟混合信号处理的集成电路.数字电 ...

  9. JavaFx实现倒计时按钮组件(类似发送激活码)

    原文地址: JavaFx实现倒计时按钮组件(类似发送激活码) - Stars-One的杂货小窝 本文基于TornadoFx框架进行编写,封装工具代码是kotlin版本 然后也是顺便把这个封装成了sta ...

  10. [置顶] spring巧用继承解决bean的id相同的问题

    先感叹一下:最近的项目真的很奇葩!!! 需求是这样的:我们的项目中引用了两个jar包,这两个jar包是其他项目组提供的,不能修改! 奇葩的是:这两个jar中都需要引用方提供一个相同id的bean,而b ...