1. 程式人生 > >[最短路 主席樹 Hash] Codeforces 464E #265 (Div. 1) E. The Classic Problem

[最短路 主席樹 Hash] Codeforces 464E #265 (Div. 1) E. The Classic Problem

很棒的資料結構練習題
因為邊權太大了 我們不能直接儲存
我們用主席樹!
比較直接從高位到低位找第一個不同的位 可以Hash下
每次加法 我們找到這一位之後第一個0 那麼0變為1 0之前一連串1都變成0 這裡有個小trick可以不用打標記 我們先建一棵全0的線段樹 清0直接找到對應節點接上去就好了

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
typedef unsigned
int uint; typedef unsigned long long ull; typedef pair<int,int> abcd; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9'
);c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=100205; const int M=20000005; const int P1=3,P2=5; uint p1[N+5],p2[N+5]; int ls[M],rs[M],f[M]; ull H[M]; int rtw,ncnt; inline void upd(int x,int l,int r){ int mid=(l+r)>>1; f[x]=!f[ls[x]]?f[rs[x]]:f[ls[x]]; uint x1=H[ls[x]]&((1L
L<<32)-1),y1=H[ls[x]]>>32; uint x2=H[rs[x]]&((1LL<<32)-1),y2=H[rs[x]]>>32; uint xx=x1+x2*p1[mid-l+1],yy=y1+y2*p2[mid-l+1]; H[x]=xx+((1LL<<32)*yy); } map<abcd,int> Pos; inline void Build(int &x,int l,int r){ x=++ncnt; int mid=(l+r)>>1; Pos[abcd(l,r)]=x; if (l==r){ H[x]=0; f[x]=l; return; } Build(ls[x],l,mid); Build(rs[x],mid+1,r); upd(x,l,r); } inline void Pre(){ p1[0]=p2[0]=1; for (int i=1;i<=N;i++) p1[i]=p1[i-1]*P1,p2[i]=p2[i-1]*P2; Build(rtw,1,N); } inline void set0(int &x,int y,int l,int r,int ql,int qr){ if (ql<=l && r<=qr){ x=Pos[abcd(l,r)]; return; } x=++ncnt; ls[x]=ls[y],rs[x]=rs[y]; int mid=(l+r)>>1; if (ql<=mid) set0(ls[x],ls[y],l,mid,ql,qr); if (qr>mid) set0(rs[x],rs[y],mid+1,r,ql,qr); upd(x,l,r); } inline void set(int &x,int y,int l,int r,int t){ x=++ncnt; ls[x]=ls[y],rs[x]=rs[y]; if (l==r){ f[x]=0; H[x]=(1LL<<32)+1; return; } int mid=(l+r)>>1; if (t<=mid) set(ls[x],ls[y],l,mid,t); else set(rs[x],rs[y],mid+1,r,t); upd(x,l,r); } inline int query(int x,int l,int r,int ql,int qr){ if (ql<=l && r<=qr) return f[x]; int mid=(l+r)>>1; if (qr<=mid) return query(ls[x],l,mid,ql,qr); else if (ql>mid) return query(rs[x],mid+1,r,ql,qr); else{ int d=query(ls[x],l,mid,ql,qr); if (d) return d; else return query(rs[x],mid+1,r,ql,qr); } } inline int Add(int x,int w){ int t=query(x,1,N,w,N),ret,tmp; if (t>w) set0(tmp,x,1,N,w,t-1); else tmp=x; set(ret,tmp,1,N,t); return ret; } const int P=1000000007; int ans=0,cur=1; inline void getval(int x,int l,int r){ if (l==r){ ans=(ans+cur*(H[x]!=0))%P,cur=(cur<<1)%P; return; } int mid=(l+r)>>1; getval(ls[x],l,mid); getval(rs[x],mid+1,r); } inline bool cmp(int x,int y,int l,int r){ if (l==r) return H[x]<H[y]; int mid=(l+r)>>1; if (H[rs[x]]==H[rs[y]]) return cmp(ls[x],ls[y],l,mid); else return cmp(rs[x],rs[y],mid+1,r); } struct info{ int x,d; info(int x=0,int d=0):x(x),d(d) { } bool operator < (const info &B) const{ return cmp(B.d,d,1,N); } }; struct edge{ int u,v,w,next; }G[N<<1]; int head[N],inum; inline void add(int u,int v,int w,int p){ G[p].u=u; G[p].v=v; G[p].w=w; G[p].next=head[u]; head[u]=p; } int S,T; priority_queue<info> Q; int dis[N],pre[N]; int vst[N]; #define V G[p].v inline void Dij(){ Q.push(info(S,rtw)); vst[S]=1; dis[S]=rtw; while (!Q.empty()){ int u=Q.top().x,d=Q.top().d; Q.pop(); if (dis[u]!=d) continue; for (int p=head[u];p;p=G[p].next){ int nw=Add(d,G[p].w); if (!vst[V] || cmp(nw,dis[V],1,N)){ vst[V]=1; dis[V]=nw; pre[V]=u; Q.push(info(V,nw)); } } } } int n,m; int pnt,lst[N]; int main(){ int iu,iv,iw; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(m); Pre(); for (int i=1;i<=m;i++) read(iu),read(iv),read(iw),iw++,add(iu,iv,iw,++inum),add(iv,iu,iw,++inum); read(S); read(T); Dij(); if (!vst[T]) printf("-1\n"); else{ getval(dis[T],1,N); printf("%d\n",ans); for (int t=T;t;t=pre[t]) lst[++pnt]=t; printf("%d\n",pnt); for (int i=pnt;i;i--) printf("%d ",lst[i]); } return 0; }