zoukankan      html  css  js  c++  java
  • 洛谷p2483 模板k短路 可持久化可并堆

    俞鼎力大牛:堆得可持久化

    直接上代码?

    #include<bits/stdc++.h>
    #define eps 1e-8
    using namespace std;
    int head[10005],cnt=-1,v[10005],rt[10005],mark[1000005],ans,fa[10005];
    int n,m,tot;
    double se,dis[10100];
    priority_queue<pair<double,int > >q;//这里注意,是double ,int 
    struct Heap{
        int ls,rs,dist,to;//左儿子 右儿子 左偏树内点的dist,每个点对应边的终点  
        double w;//小根堆每个点的权值 
    }tr[30000010];
    struct node{
        int next,to;
        double w;
    }e[10000010];
    void add(int from,int to,double w){
        e[++cnt].next=head[from];
        e[cnt].to=to;
        e[cnt].w=w;
        head[from]=cnt;
    }
    int merge(int x,int y){
        if(!x||!y)return x+y;
        if(tr[x].w-tr[y].w>=eps)swap(x,y);
        int p=++tot;
        tr[p]=tr[x];
        tr[p].rs=merge(tr[p].rs,y);
        if(tr[tr[p].ls].dist<tr[tr[p].rs].dist)swap(tr[p].ls,tr[p].rs);
        tr[p].dist=tr[tr[x].rs].dist+1;
        return p;
    }
    void dijkstra(){
        memset(v,0,sizeof v);
        memset(dis,127,sizeof dis);
        dis[n]=0;
        q.push(make_pair(0,n));
        while(!q.empty()){
            int from=q.top().second;
            q.pop();
            if(v[from])continue;
            v[from]=1;
            for(int i=head[from];~i;i=e[i].next){
                if(i&1){//反向边 
                    int to=e[i].to;
                    if(dis[to]-(dis[from]+e[i].w)>eps){
                        dis[to]=dis[from]+e[i].w;
                        q.push(make_pair(-dis[to],to));
                    }
                }
            }
        }
    }//djk跑一遍从终点反向往回走的最短路树 
    void dfs(int from){
        v[from]=1;
        for(int i=head[from];i!=-1;i=e[i].next){
            int to=e[i].to;
            if(i&1){
                if(v[to])continue;
                if(fabs(dis[from]+e[i].w-dis[to])<eps){
                    fa[to]=from;
                    mark[i^1]=1;
                    dfs(to);
                }
            }
        }
    }//标记一下最短路树上有哪些边
    int newnode(double w,int to){
        int x=++tot;
        tr[x].w=w;
        tr[x].dist=1;
        tr[x].to=to;
        return x;
    }
    int main(){
        memset(head,-1,sizeof head);
        scanf("%d%d%lf",&n,&m,&se);
        for(int i=1;i<=m;i++){
            int x,y;
            double z;
            scanf("%d%d%lf",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        }
        dijkstra();
        memset(v,0,sizeof v);
        dfs(n);
        for(int i=0;i<=cnt;i+=2){
            if(!mark[i]){
                int from=e[i^1].to,to=e[i].to;
                if(dis[from]==dis[0]||dis[to]==dis[0])continue;
                rt[from]=merge(rt[from],newnode(dis[to]+e[i].w-dis[from],to));
            }
        }//把不在最短路树上的路径加入堆;
        //权值是"走不在最短路树上的边的路径长度与最短路的路径长度的差值"
        for(int i=1;i<=n;i++){
            q.push(make_pair(-dis[i],i));
        } 
        for(int i=1;i<=n;i++){
            int from=q.top().second;
            q.pop();
            if(fa[from])rt[from]=merge(rt[from],rt[fa[from]]);
        }//把在最短路树上的路径加入堆 
        if(dis[1]-se<eps)se-=dis[1],ans++; //走最短路的情况
        if(rt[1])q.push(make_pair(-tr[rt[1]].w,rt[1]));//假如rt[1]没有说明从n根本到不了1
        while(!q.empty()){
            int from=q.top().second;
            double cur=q.top().first; 
            double w=dis[1]-cur;//当前路径的长度
            if(w-se>=eps)break;//能量耗完
            q.pop();
            se-=w;
            ans++;//找到一条k路径 
            for(int i=0;i<2;i++){//加当前的堆的路径 
                int to=i?tr[from].rs:tr[from].ls;
                if(to)q.push(make_pair(cur+tr[from].w-tr[to].w,to));//一条新的路径 加入优先队列 
            }//把左儿子和右儿子加入优先队列,因为是小根堆 ,所以这样加肯定是从小到大的; 
            if(rt[tr[from].to])q.push(make_pair(cur-tr[rt[tr[from].to]].w,rt[tr[from].to])); //加to对应的新的堆的路径; 
        }
        printf("%d
    ",ans);
    }
  • 相关阅读:
    Oracle执行计划(三)
    执行计划-数据访问方式(全表扫描与4种索引的方式)
    比较两个文件内容是否相同
    设置myeclipse控制台输出到文件中
    Java出现NoSuchElementException异常
    Spring-Aop编程(三)-AspectJ
    Spring AOP编程(二)-AOP实现的三种方式
    Spring AOP编程(一)-AOP介绍
    java.lang.OutOfMemoryError: GC overhead limit exceeded异常处理
    Spring 属性依赖注入
  • 原文地址:https://www.cnblogs.com/passione-123456/p/11788117.html
Copyright © 2011-2022 走看看