学习地址:【配对堆】 - 大米饼 - 博客园
问题描述:N个点,M条边的有向图,求点1到点N的最短路(保证存在)。 1<=N<=1000000,1<=M<=10000000
Code:
#include<bits/stdc++.h>
#define maxn 1000005
#define maxm 10000005
#define LL long long
using namespace std;
char cb[1<<18],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<18,stdin),cs==ct)?0:*cs++)
inline void read(int &a){
char c;while(!isdigit(c=getc()));
for(a=c-'0';isdigit(c=getc());a=a*10+c-'0');
}
const int N = 1000005, M = 10000005;
struct Bin{
int S[M],sz,id;
int get(){return sz?S[sz--]:++id;}
void del(int x){S[++sz]=x;}
}Edge;
int n,m;
LL dis[maxn];
struct Pairing_Heap{
int rt,head[N],fa[N],tmp; struct E{int nxt,to;}e[M];
void addedge(int x,int y){e[tmp=Edge.get()]=(E){head[x],y},head[x]=tmp;}
int merge(int x,int y){dis[x]>dis[y]&&(swap(x,y),0);addedge(x,y);return fa[y]=x;}
//void push(int x){rt=rt?merge(x,rt):x;}
//int top(){return rt;}
void upd(int x){fa[x]=0,rt=merge(x,rt);}
void pop(){
static int stk[N*2],tp; tp=0;
for(int i=head[rt],v;i;i=e[i].nxt) Edge.del(i),fa[v=e[i].to]==rt&&(fa[stk[++tp]=v]=0);
head[rt]=0;
for(int i=1;i<tp;i+=2) stk[++tp]=merge(stk[i],stk[i+1]);
rt=stk[tp];
}
}q;
int X[maxm],Y[maxm],Z[maxm];
int *fir[maxn],pt[maxn],Fir[maxm],*F=Fir,*w[maxn],Cst[maxm],*W=Cst,deg[maxn];
void Dijkstra(){
memset(dis,0x3f,sizeof dis);
dis[q.rt=1]=0;
while(q.rt){
int u=q.rt;q.pop();
int *to=fir[u],*cst=w[u];
for(int i=0;i<deg[u];i++,to++,cst++)
if(dis[*to]>dis[u]+*cst) dis[*to]=dis[u]+*cst,q.upd(*to);
}
}
int main()
{
//int t=clock();
int T=0,rxa,rxc,rya,ryc,rp,x=0,y=0,a,b;
read(n),read(m);
/*read(T),read(rxa),read(rxc),read(rya),read(ryc),read(rp);
for(int i=1;i<=T;i++){
x=(1ll*x*rxa+rxc)%rp,y=(1ll*y*rya+ryc)%rp;
a=min(x%n+1,y%n+1),b=max(x%n+1,y%n+1);
deg[X[i]=a]++,Y[i]=b,Z[i]=(1e8)-100*a;
}*/
for(int i=T+1;i<=m;i++) read(X[i]),deg[X[i]]++,read(Y[i]),read(Z[i]);
for(int i=1;i<=n;i++) fir[i]=F,w[i]=W,F+=deg[i],W+=deg[i];
for(int i=1,u;i<=m;i++) u=X[i],fir[u][pt[u]]=Y[i],w[u][pt[u]++]=Z[i];
//cout<<clock()-t<<endl;
Dijkstra();
printf("%lld\n",dis[n]);
//cout<<clock()-t<<endl;
}