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
%d ",dep,x);return ;}
	dfs(pre[x],dep+1);
	printf("%d ",x);
}
inline void Output(int x){
	printf("%d
",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;
}

原文地址:https://www.cnblogs.com/Yuzao/p/8715902.html