#主席树,Dijkstra,哈希#CF464E The Classic Problem
题目
边权均为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的更多相关文章
- 数据结构(主席树):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 ...
- LCA+主席树 (求树上路径点权第k大)
SPOJ 10628. Count on a tree (树上第k大,LCA+主席树) 10628. Count on a tree Problem code: COT You are given ...
- 51Nod1863 Travel 主席树 最短路 Dijkstra 哈希
原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1863.html 题目传送门 - 51Nod1863 题意 有 n 个城市,有 m 条双向路径连通它们 ...
- 【CF464E】The Classic Problem(主席树+最短路)
点此看题面 大致题意: 给你一张无向图,每条边的边权为\(2^{x_i}\),求\(s\)到\(t\)的最短路. 最短路 最短路,首先考虑\(Dijkstra\).这里用\(SPFA\)似乎不太好,因 ...
- Codeforces 464E The Classic Problem(主席树+最短路+哈希,神仙题)
题目链接 题意:给出一张 \(n\) 个点 \(m\) 条边的无向图,第 \(i\) 条边连接 \(u_i,v_i\),边权为 \(2^{w_i}\),求 \(s\) 到 \(t\) 的最短路. \( ...
- Codeforces 464E #265 (Div. 1) E. The Classic Problem 主席树+Hash
E. The Classic Problem http://codeforces.com/problemset/problem/464/E 题意:给你一张无向带权图,求S-T的最短路,并输出路径.边权 ...
- BZOJ_3207_花神的嘲讽计划Ⅰ_哈希+主席树
BZOJ_3207_花神的嘲讽计划Ⅰ_哈希+主席树 Description 背景 花神是神,一大癖好就是嘲讽大J,举例如下: “哎你傻不傻的![hqz:大笨J]” “这道题又被J屎过了!!” “J这程 ...
- CodeForces 464E The Classic Problem | 呆克斯歘 主席树维护高精度
题意描述 有一个\(n\)点\(m\)边的无向图,第\(i\)条边的边权是\(2^{a_i}\).求点\(s\)到点\(t\)的最短路长度(对\(10^9 + 7\)取模). 题解 思路很简单--用主 ...
- Codeforces 464E The Classic Problem (最短路 + 主席树 + hash)
题意及思路 这个题加深了我对主席树的理解,是个好题.每次更新某个点的距离时,是以之前对这个点的插入操作形成的线段树为基础,在O(logn)的时间中造出了一颗新的线段树,相比直接创建n颗线段树更省时间. ...
- bzoj 1901: Zju2112 Dynamic Rankings -- 主席树,树状数组,哈希
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MB Description 给定一个含有n个数的序列a[1] ...
随机推荐
- QT - Day 6
跟着视频教程创建了翻金币的项目,花了好几个晚上才学习完. 视频地址:最新QT从入门到实战 感谢视频的教学,真是受益匪浅. 后面的代码参考了老师的模板以及文档的抒写格式. 发布到随笔中的目的一方面为了完 ...
- 【LeetCode回溯算法#09】全排列,排列问题以及其中涉及的去重操作
全排列 力扣题目链接 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 .你可以 按任意顺序 返回答案. 示例 1: 输入:nums = [1,2,3] 输出:[[1,2,3],[1, ...
- 【LeetCode二叉树#05】平衡二叉树
力扣题目链接(opens new window)](https://leetcode.cn/problems/balanced-binary-tree/) 给定一个二叉树,判断它是否是高度平衡的二叉树 ...
- 第一百一十六篇: JavaScript理解对象
好家伙,本篇为<JS高级程序设计>第八章"对象.类与面向对象编程"学习笔记 1.关于对象 ECMA-262将对象定义为一组属性的无序集合.严格来说,这意味着对象就是 ...
- Redis灵魂11问
目录 说说redis都有哪些数据类型吧 Redis为什么快呢? 那为什么Redis6.0之后又改用多线程呢? 知道什么是热key吗?热key问题怎么解决? 什么是缓存击穿.缓存穿透.缓存雪崩? 缓存击 ...
- 初识JavaScript逆向——以网易云音乐和招标网站为例
前言:需要掌握一定的JavaScript基础,能看懂基础的JavaScript代码. 我们平常在浏览网站的时候会看到许多加密的参数,如果需要知道它的原始数据,就需要知道整个加密过程,所以本篇文章就来介 ...
- C++ //排序案列 //描述:将person自定义数据类型进行排序,Person中有属性 姓名,年龄,身高 //排序规则: 按照年龄进行的升序,如果年龄相同按照身高进行降序
1 //排序案列 2 //描述:将person自定义数据类型进行排序,Person中有属性 姓名,年龄,身高 3 //排序规则: 按照年龄进行的升序,如果年龄相同按照身高进行降序 4 5 #inclu ...
- 闭关修炼180天----手写迷你版的tomcat-Minicat
手写迷你版的tomcat-Minicat 小谈Tomcat Tomcat请求处理⼤致过程 Tomcat是⼀个Http服务器(能够接收并且处理http请求,所以tomcat是⼀个http服务器) 我们使 ...
- Django进阶之路由层和视图层
Django的路由系统 [1]什么是URL配置(URLconf) URL调度器 | Django 文档 | Django (djangoproject.com) URL配置(URLconf)就像Dja ...
- Oracle中表字段有使用Oracle关键字的一定要趁早改!!!
一.问题由来 现在进行项目改造,数据库需要迁移,由原来的使用GBase数据库改为使用Oracle数据库,今天测试人员在测试时后台报了一个异常. 把SQL语句单独复制出来进行查询,还是报错,仔细分析原因 ...