#主席树,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] ...
随机推荐
- win32 - 在进程之间获取事件通知(CreateEvent)
只需要记住使用OpenEvent来同步Event对象. Project A: #define _CRT_SECURE_NO_WARNINGS #include <Windows.h> #i ...
- 【Android逆向】反调试绕过
1. 拿到52pojie的反调试挑战apk 链接: https://www.52pojie.cn/thread-742686-1-1.html 的附件中 2. 项目进行安装,点开app,同时挑战成功, ...
- [WEB安全] CSRF攻击和防御
一.什么是CSRF 跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或 ...
- Hello-FPGA CoaXPress 2.0 FPGA DEVICE IP Core Demo
Hello-FPGA CoaXPress 2.0 Device FPGA IP Core Demo 1 说明 本手册针对Helllo-FPGA的CoaXPress 2.0 DEVICE FPG ...
- 【Azure 存储服务】关于对Azure Storage Account 的 Folder 权限管理和设定
问题描述 在一个storage account下面有很多folder,需要对不同的folder设置不同的权限给到不同的用户来访问使用,怎么样设定比较合理? 问题解答 一:可以使用SAS共享访问签名进行 ...
- SpringCloud 网关组件Gateway
官网文档: https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/ 1. 概述 1.1 什么是网关 ...
- 在Linux下开启指定端口号
1.查看某个端口是否已开启,如果提示no表示未开启 #8888表示要查询的端口号firewall-cmd --query-port=8888/tcp 2.永久开启端口号,提示 success 表示成功 ...
- Android学习之文件存储
•前言 任何一个应用程序,其实说白了就是在不停地和数据打交道,我们聊QQ.看新闻.刷微博,所关心的都是里面的数据, 没有数据的应用程序就变成了一个空壳子,对用户来说没有任何实际用途. 那么这些数据都是 ...
- vscode 对js文件不格式化的修正方案 settings.json
修正1 "javascript.format.enable": true, // 这里false 改true 修正2 注释掉这个地方 // "[javascript]&q ...
- vue-cli-service build 时间戳 方便查看bug发布时间和项目发布时间对比
vue.config.js let ret = '' const date = new Date() ret += date.getFullYear() ret += '-'+ (date.getMo ...