最短路(road)配对堆优化dij

题目链接、

 

bzoj3040、限时60s可把我吓坏了

程序跑了10s

点1e6,边1e7

考虑配对堆优化、

#说实话如果不涉及大量的改值的话,配对堆也没传说中的快

 

/*author:revolIA*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6+7,maxm = 1e7+7;
struct Stack{
    int Stk[maxn],cnt,k;
    void init(){cnt = k = 0;}
    int Get(){return cnt?Stk[cnt--]:++k;}
    void Save(int idx){Stk[++cnt] = idx;}
}Edge,Node;
struct Pairing_heap{
    int Fa[maxn],head[maxn],inq[maxn],k,root;
    int Stk[maxn],cnt;
    struct {int to,next;}e[maxn];
    pair<int,int> val[maxn];
    void init(){root = k = cnt = 0;}
    void Add(int u,int v){
        e[k = Edge.Get()] = {v,head[u]};
        head[u] = k;
    }
    int Merge(int u,int v){
        if(val[u]>val[v])u^=v^=u^=v;
        Add(Fa[v] = u,v);
        return u;
    }
    void Change(pair<int,int> x){
        int u = inq[x.second];
        Fa[u] = 0;
        val[u].first = x.first;
        if(u!=root){
            root = Merge(u,root);
        }
    }
    void push(pair<int,int> x,int u = 0){
        if(inq[x.second]){
            Change(x);
        }else{
            val[u = Node.Get()] = x;
            inq[x.second] = u;
            root = root?Merge(root,u):u;
        }
    }
    pair<int,int> Top(){return val[root];}
    void pop(){
        cnt = 0;
        for(int i=head[root];i;i=e[i].next){
            int v = e[i].to;
            Edge.Save(i);
            if(Fa[v] == root){
                Fa[Stk[++cnt] = v] = 0;
            }
        }
        Fa[root] = head[root] = 0;
        inq[root] = 0;
        Node.Save(root),root = 0;
        int p = 0;
        while(p<cnt){
            ++p;
            if(p == cnt){
                root = Stk[cnt];
                return;
            }
            int u = Stk[p],v = Stk[++p];
            Stk[++cnt] = Merge(u,v);
        }
    }
    int Empty(){
        return !root;
    }
}heap;
int n,m,s;
int Next[maxm],to[maxm],val[maxm],head[maxn],cnt;
void Add(int u,int v,int w){
    to[++cnt] = v,val[cnt] = w;
    Next[cnt] = head[u];
    head[u] = cnt;
}
int dis[maxn];
void dijstkra(int s){
    for(int i=1;i<=n;i++)dis[i] = 0x3f3f3f3f;
    dis[s] = 0;
    Edge.init(),Node.init();
    heap.init();
    heap.push({0,s});
    while(!heap.Empty()){
        pair<int,int> top = heap.Top();
        heap.pop();
        for(int i=head[top.second];i;i=Next[i]){
            int Len =  dis[top.second]+val[i];
            if(Len<dis[to[i]]){
                dis[to[i]] = Len;
                heap.push({Len,to[i]});
            }
        }
    }
}
int main(){
    int T,rxa,rxc,rya,ryc,rp,x,y,z,a,b;
    scanf("%d%d",&n,&m);
    scanf("%d%d%d%d%d%d",&T,&rxa,&rxc,&rya,&ryc,&rp);
    x = y = z = 0;
    for(int i=1;i<=T;i++){
        x = (x*rxa+rxc)%rp;
        y = (y*rya+ryc)%rp;
        a = min(x%n+1,y%n+1);
        b = max(y%n+1,y%n+1);
        int Len = 1e8-100*a;
        Add(a,b,Len);
    }
    for(int i=T+1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        Add(u,v,w);
    }
    dijstkra(1);
    printf("%d\n",dis[n]);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值