题目大意

给定一张$n$个点, $m$条边的无向图,求$S$ 到$T$的最短路,其中边权都是$2^k$的形式$n,m,k<=10^5$,结果对$10^9+7$取模

题解

大佬好厉害

跑一边dijstra大家应该都想的到

但问题是维护最短路的距离怎么实现

我太菜了除了python啥都想不到

我们可以把距离拆成每一位,因为每一次只会加上一个数,直接开主席树维护就好了

时间复杂度什么的……感性理解一下就好了

比较大小直接二分哈希

 //minamoto
#include<bits/stdc++.h>
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,:;}
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
const int N=1e5+,mod=1e9+;
int n,m,head[N],Next[N<<],ver[N<<],edge[N<<];
int S,T,lim,b[N<<],rt[N],Pre[N],tot,cnt;
int L[N*],R[N*],sum[N*];
inline void add(int u,int v,int e){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=e;
}
bool cmp(int u,int v,int l,int r){
if(l==r) return sum[u]>sum[v];
int mid=(l+r)>>;
if(sum[R[u]]==sum[R[v]]) return cmp(L[u],L[v],l,mid);
else return cmp(R[u],R[v],mid+,r);
}
int update(int last,int &now,int l,int r,int k){
L[now=++cnt]=L[last],R[now]=R[last];
if(l==r){
sum[now]=sum[last]^;
return sum[last];
//每一个节点存的只有一位,如果加之前是1就要进位
}
int mid=(l+r)>>,res;
if(k>mid) res=update(R[last],R[now],mid+,r,k);
else{
res=update(L[last],L[now],l,mid,k);
if(res) res=update(R[last],R[now],mid+,r,k);
}
sum[now]=(1ll*sum[R[now]]*b[mid-l+]+sum[L[now]])%mod;
return res;
}
struct node{
int x,rt;
bool operator <(const node &b)const
{return cmp(rt,b.rt,,lim);}
};
priority_queue<node> q;
void dfs(int u,int dep){
if(u==S){printf("%d\n%d ",dep,u);return;}
dfs(Pre[u],dep+);
printf("%d ",u);
}
void print(int u){
printf("%d\n",sum[rt[u]]);
dfs(u,);exit();
}
int main(){
//freopen("testdata.in","r",stdin);
n=read(),m=read();
for(int i=;i<=m;++i){
int u,v,e;
u=read(),v=read(),e=read();
add(u,v,e);
cmax(lim,e);
}
lim+=;
b[]=;for(int i=;i<=lim;++i) b[i]=(1ll*b[i-]<<)%mod;
S=read(),T=read();
q.push((node){S,rt[S]});
while(!q.empty()){
node u=q.top();q.pop();
if(u.rt!=rt[u.x]) continue;
//如果不一样,说明已经在主席树上被修改了
//就给普通的判dijkstra一样就好了
if(u.x==T) print(T);
for(int i=head[u.x];i;i=Next[i]){
int v=ver[i],RT;
update(u.rt,RT,,lim,edge[i]);
if(!rt[v]||cmp(rt[v],RT,,lim))
rt[v]=RT,q.push((node){v,rt[v]}),Pre[v]=u.x;
}
}
puts("-1");
return ;
}

Codeforces 464E. The Classic Problem的更多相关文章

  1. [Codeforces 464E] The Classic Problem(可持久化线段树)

    [Codeforces 464E] The Classic Problem(可持久化线段树) 题面 给出一个带权无向图,每条边的边权是\(2^{x_i}(x_i<10^5)\),求s到t的最短路 ...

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

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

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

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

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

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

  5. CF 464E The Classic Problem

    补一补之前听课时候的题. 考虑使用dij算法求最短路,因为边权存不下,所以考虑用主席树维护二进制位,因为每一次都只会在一个位置进行修改,所以可以暴力进位,这样均摊复杂度是对的. <算法导论> ...

  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. [codeforces 528]B. Clique Problem

    [codeforces 528]B. Clique Problem 试题描述 The clique problem is one of the most well-known NP-complete ...

  8. codeforces.com/contest/325/problem/B

    http://codeforces.com/contest/325/problem/B B. Stadium and Games time limit per test 1 second memory ...

  9. Codeforces 442B Andrey and Problem(贪婪)

    题目链接:Codeforces 442B Andrey and Problem 题目大意:Andrey有一个问题,想要朋友们为自己出一道题,如今他有n个朋友.每一个朋友想出题目的概率为pi,可是他能够 ...

随机推荐

  1. 两个不同vim之间复制内容

    常规想法是打开两个vim,然后进行yy和p操作,但是实践证明根本是不行的.此时,我们需要分割窗口,然后就可以复制粘贴了.步骤如下: 假设我要把srv.c文件的readline函数整体复制到cli.c文 ...

  2. UV-Sprite动画

    [UV-Sprite动画] 下文以单行Sprite纹理作为动画贴图.首先需要输入纹理宽度.Sprint数量.速度: 计算每个Sprite的像素宽与UV宽: 根据_Time,计算当前显示第几个Sprit ...

  3. 【codevs3160】 LCS 【后缀自动机】

    题意 给出两个字符串,求它们的最长公共子串. 分析 后缀自动机的基础应用. 比如两个字符串s1和s2,我们把s1建为SAM,然后根据s2跑,找出s2每个前缀的最长公共后缀. 我们可以理解为,当向尾部增 ...

  4. Python中super详解

    转至:https://mozillazg.com/2016/12/python-super-is-not-as-simple-as-you-thought.html 说到 super, 大家可能觉得很 ...

  5. Opencv 分水岭分割图片

    #include <iostream>#include <opencv2/opencv.hpp> using namespace std;using namespace cv; ...

  6. 269. Alien Dictionary火星语字典(拓扑排序)

    [抄题]: There is a new alien language which uses the latin alphabet. However, the order among letters ...

  7. CS API 测试2

    //删除数据中心 http://192.168.150.16:8900/client/api?command=deleteZone&id=c2d4f46a-51af-4806-8378-4b3 ...

  8. vpp命令总结

    create sub BondEthernet0 834 创建子接口,tag是834 set interface ip table BondEthernet0.834 1 将此接口设置在fib 1里 ...

  9. 怎样下载网页中的js文件?

    1.按下F12,会看到调试的界面,如下图所示,先点击最上面的Resources选项,Frames--(你想下载的网址)--Script,下面就是全部的js文件啦,网站的图片啊什么的都可以下载了.

  10. poj 2007 Scrambled Polygon

    #include<stdio.h> #include<algorithm> using namespace std; #define Max 60 struct Point { ...