Codeforces 464E. The Classic Problem
Description
给定一张 \(n\) 个点,\(m\) 条边的无向图,求 \(S\) 到 \(T\) 的最短路,其中边权都是 \(2^k\) 的形式
\(n,m,k<=10^5\)
题面
Solution
与 \(NOI\) 整数类似
不过此题没有减法,那么复杂度可以均摊
我们按普通 \(dijkstra\) 那样跑,把 \(dis\) 数组改成一棵线段树
由于每一次只会加上一个数,用主席树维护一下就行了
对于进位,因为没有减法,所以产生 \(k\) 个 \(1\),至少需要 \(k\) 次操作,暴力改一次就是 \(O(1)\) 的了
那么暴力改复杂度就是对的了,代码十分简单
比较大小的方式就更二分哈希一样:二分到不同的位置,再判断这个位置
这题本身给了一个 \(hash\) ,\(seed=2,mod=10^9+7\) ,也可以过,但最好还是手写的好
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,mod=1e9+7;
int n,m,head[N],nxt[N*2],to[N*2],dis[N*2],num=0;
int S,T,lim,b[N*2],tt=0,rt[N],pre[N];
inline void link(int x,int y,int z){
nxt[++num]=head[x];to[num]=y;head[x]=num;dis[num]=z;
}
struct Seg{
int ls,rs,w;
}tr[N*120];
inline bool comp(int x,int y,int l,int r){
if(l==r)return tr[x].w>tr[y].w;
int mid=(l+r)>>1;
if(tr[tr[x].rs].w==tr[tr[y].rs].w)return comp(tr[x].ls,tr[y].ls,l,mid);
return comp(tr[x].rs,tr[y].rs,mid+1,r);
}
inline bool add(int x,int &y,int l,int r,int sa){
y=++tt;tr[y]=tr[x];
if(l==r){
tr[y].w=tr[x].w^1;
return tr[x].w;
}
int mid=(l+r)>>1,ret;
if(sa>mid)ret=add(tr[x].rs,tr[y].rs,mid+1,r,sa);
else{
ret=add(tr[x].ls,tr[y].ls,l,mid,sa);
if(ret)ret=add(tr[x].rs,tr[y].rs,mid+1,r,mid+1);
}
tr[y].w=(1ll*tr[tr[y].rs].w*b[mid-l+1]+tr[tr[y].ls].w)%mod;
return ret;
}
struct data{
int x,rt;
bool operator <(const data &p)const{return comp(rt,p.rt,0,lim);}
};
priority_queue<data>Q;
inline void dfs(int x,int dep){
if(x==S){printf("%d\n%d ",dep,x);return ;}
dfs(pre[x],dep+1);
printf("%d ",x);
}
inline void Output(int x){
printf("%d\n",tr[rt[x]].w);
dfs(x,1);exit(0);
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>n>>m;
int x,y,z;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
link(x,y,z);link(y,x,z);lim=max(lim,z);
}
lim+=100;
b[0]=1;for(int i=1;i<=lim;i++)b[i]=1ll*b[i-1]*2%mod;
cin>>S>>T;
Q.push((data){S,rt[S]});
while(!Q.empty()){
data t=Q.top();Q.pop();
if(t.rt!=rt[t.x])continue;
if(t.x==T)Output(T);
for(int i=head[t.x];i;i=nxt[i]){
int u=to[i],RT;
add(t.rt,RT,0,lim,dis[i]);
if(!rt[u] || comp(rt[u],RT,0,lim))
rt[u]=RT,Q.push((data){u,rt[u]}),pre[u]=t.x;
}
}
puts("-1");
return 0;
}