配对堆模板

学习地址:【配对堆】 - 大米饼 - 博客园
问题描述: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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值