[BZOJ 3040] Dijktra && 手写堆 (非普通模板)

5 篇文章 0 订阅
2 篇文章 0 订阅

Dijkstra求最短路。

这题用普通的手写堆还过不了。。

考虑更新一个堆中的元素时,普通的优先队列是再push一个进去,但是手写堆就不需要这样,只要找到这个元素在堆中位置再尝试向上交换就行了,代码中就是update函数。别的pop(),top()之类操作和普通堆都差不多。最开始要把所有元素放进堆里。

由于每次还要找到一个元素在堆中的位置,所以用index[]数组记录,交换堆中的元素时切记也要交换index[]数组!!!由于index好像重名所以代码中用了define。

#include<bits/stdc++.h>
#define lson (x<<1)
#define rson (x<<1|1)
#define ll long long
#define index ind
using namespace std;
const int N=1000001;
const int M=N*10;
const ll INF=1e18;
int n,m;
int T,rxa,rxc,rya,ryc,rp;
int cnt,Next[M],head[N],v[M],w[M];
ll dis[N];
int h[N],index[N];
int L;
bool b[N];

inline void read(int &x){
    char ch=getchar();x=0;
    for(;ch<'0'||ch>'9';ch=getchar());
    for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
}

inline void read(ll &x){
    char ch=getchar();x=0;
    for(;ch<'0'||ch>'9';ch=getchar());
    for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
}

inline void add(ll x,ll y,ll z){
    Next[++cnt]=head[x];
    head[x]=cnt;
    v[cnt]=y;
    w[cnt]=(int) z;
}

void Swap(int x,int y){
    swap(index[h[x]],index[h[y]]);
    swap(h[x],h[y]);
}

void update(int u){
    int x=index[u];
    while(x>1&&dis[h[x]]<dis[h[x>>1]]){
        Swap(x,x>>1);
        x>>=1;
    }
}

int top(){
    return h[1];
}

void pop(){
    h[1]=h[L--];
    index[h[1]]=1;    //就是少写了这一句呜呜呜
    h[L+1]=0;
    int x=1;
    while(rson<=L){
        if (dis[h[x]]<=dis[h[lson]]&&dis[h[x]]<=dis[h[rson]]) break;
        int w=0;
        if (dis[h[lson]]<dis[h[rson]]) w=lson;
         else w=rson;
        Swap(w,x);
        x=w;
    }
    if (lson<=L&&dis[h[lson]]<dis[h[x]]) Swap(lson,x);
}

inline void dijk(){
    for(int i=1;i<=n;++i){
        int x=top();
        pop();
        b[x]=1;
        for(int j=head[x];j!=-1;j=Next[j])
         if (!b[v[j]]&&dis[x]+w[j]<dis[v[j]]){
            dis[v[j]]=dis[x]+w[j];
            update(v[j]);
         }
    }
}

int main(){
    memset(head,-1,sizeof head);
    read(n);read(m);
    read(T);read(rxa);read(rxc);read(rya);read(ryc);read(rp);
    ll x=0,y=0,z=0;
    ll a,b;
    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);
        add(a,b,1e8-100*a);
    }
    for(int i=T+1;i<=m;++i){
        read(x);read(y);read(z);
        add(x,y,z);
    }

    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    for(int i=1;i<=n;i++){   //将元素放进堆里
        h[++L]=i;
        index[i]=i;
    }

    dijk();
    if (dis[n]>1e17) cout<<"-1"<<endl;else cout<<dis[n]<<endl;
    return 0;
}

一开始看到题目还以为是个大水题。。
mdzz调了我两天因为少写了一句交换序号。。拍了30+万组数据才拍出来。。
不知道517从哪里搞来的题 517好像把这题撤了(可能是由于他自己写T了。。)

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可 6私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值