zoukankan      html  css  js  c++  java
  • [学习笔记]k短路

    A*:我已经忘了怎么写了,反正n=30,m=1000都能卡掉。。。

    正解:可持久化左偏树+堆维护可能集合

    原论文:http://www.docin.com/p-1387370338.html

    概括:

    结论:

    1.t为根求最短路树T,定义P'为路径s-t的路径P和T没有交集的部分,P’和P都是有序边集

    对于P'中相邻边一定存在tail和head的祖先后代关系(或者重合)

    2.新定义边的代价:dis[v]+w-dis[u],即换边走的额外可能花费

    这样一个P就是:dis[1~n]+∑e∈P' newweight[e]

    3.P和P'一一对应。

    求法:

    1.T为根求最短路树

    2.非树边放进u的左偏树内,

    3.dfs可持久化合并堆,得到到根路径上的出边的堆

    4.堆维护四元组(u,v,pos,val)边集倒数第二条边tail是u,倒数第一条边tail是v,v的这个边的左偏树节点编号pos,P’的代价val

    更新:

    A.v找到rt[v]最小的加入P的末尾

    B.u找到rt[u]下一个最小的边作为新的v和pos,这个边一定是pos的左儿子或者右儿子

    初始:(0,1,*,0)要特判

    注意特判:

    A.rt[v]=0?

    B.pos没有左右儿子?

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define fi first
    #define se second
    #define mk(a,b) make_pair(a,b)
    #define numb (ch^'0')
    #define pb push_back
    #define solid const auto &
    #define enter cout<<endl
    #define pii pair<int,int>
    using namespace std;
    typedef long long ll;
    template<class T>il void rd(T &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
    template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
    template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('
    ');}
    
    namespace Miracle{
    const int N=5005;
    const int M=200000+5;
    int n,m;
    double E;
    struct node{
        int nxt,to;
        double val;
    }e[M];
    int hd[N],cnt=0;
    void add(int x,int y,double z){
        e[++cnt].nxt=hd[x];
        e[cnt].to=y;e[cnt].val=z;
        hd[x]=cnt;
    }
    
    struct edge{
        int x,y;
        double z;
    }b[M];
    double dis[N];
    struct po{
        int x;double val;
        po(){}
        po(int xx,double vv){
            x=xx;val=vv;
        }
        bool friend operator <(po a,po b){
            return a.val>b.val;
        }
    };
    priority_queue<po>q;
    bool vis[N];
    int pre[N];
    void dij(){
        memset(dis,127,sizeof dis);
        dis[n]=0;
        q.push(po(n,0));
        while(!q.empty()){
            po now=q.top();q.pop();
            if(vis[now.x]) continue;
            int x=now.x;
            vis[x]=1;
            for(reg i=hd[x];i;i=e[i].nxt){
                int y=e[i].to;
                if(dis[y]>dis[x]+e[i].val){
                    dis[y]=dis[x]+e[i].val;
                    pre[y]=i;
                    q.push(po(y,dis[y]));
                }
            }
        }
    }
    bool on[M];
    struct tr{
        int ls,rs;
        int d,id;
        double val;
        tr(){}
        tr(double v,int ddd){
            ls=0,rs=0;val=v;d=1;id=ddd;
        }   
    }t[M*20];
    int tot;
    int rt[N];
    int merge(int x,int y,int typ){
        if(!x||!y) return x+y;
        if(t[x].val>t[y].val) swap(x,y);
        if(typ){
            int nw=++tot;
            t[nw]=t[x];
            x=nw;
        }
        t[x].rs=merge(t[x].rs,y,typ);
        if(t[t[x].ls].d<t[t[x].rs].d) swap(t[x].ls,t[x].rs);
        t[x].d=t[t[x].rs].d+1;
        return x;
    }
    struct sol{
        int u,v,pos;
        double val;
        sol(){}
        sol(int uu,int vv,int pp,double vd){
            u=uu;v=vv;pos=pp;val=vd;
        }
        bool friend operator <(sol a,sol b){
            return a.val>b.val;
        }
    };
    void dfs(int x){
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            rt[y]=merge(rt[y],rt[x],1);
            dfs(y);
        }
    }
    priority_queue<sol>hp;
    
    int main(){
        rd(n);rd(m);scanf("%lf",&E);
        for(reg i=1;i<=m;++i){
            rd(b[i].x);rd(b[i].y);scanf("%lf",&b[i].z);
            add(b[i].y,b[i].x,b[i].z);
        }
        dij();
        // for(reg i=1;i<=n;++i){
        //     cout<<i<<" : "<<dis[i]<<endl;
        // }
        memset(hd,0,sizeof hd);
        cnt=0;
        for(reg i=1;i<n;++i){
            on[pre[i]]=1;
            int id=pre[i];
            add(b[id].y,b[id].x,b[id].z);
        }
        for(reg i=1;i<=m;++i){
            if(!on[i]){
                t[++tot]=tr(dis[b[i].y]+b[i].z-dis[b[i].x],i);
                rt[b[i].x]=merge(rt[b[i].x],tot,0);
            }
        }
        dfs(n);
        hp.push(sol(0,1,-233,0));
        double st=dis[1];
        ll ans=0;
        while(!hp.empty()){
            sol now=hp.top();hp.pop();
            E-=now.val+st;
            if(E<0) break;
            ++ans;
            int u=now.u,v=now.v;
            if(now.v==1&&now.u==0){
                if(rt[1]){
                    sol lp=now;
                    lp.u=1;
                    lp.pos=rt[1];
                    lp.val=t[rt[1]].val;
                    lp.v=b[t[rt[1]].id].y;
                    hp.push(lp);
                }
            }else{
                if(rt[now.v]){
                    sol lp=now;
                    lp.u=v;
                    lp.pos=rt[lp.u];
                    lp.val+=t[rt[lp.u]].val;
                    lp.v=b[t[rt[lp.u]].id].y;
                    hp.push(lp);
                }
                if(t[now.pos].ls){
                    sol lp=now;
                    lp.pos=t[lp.pos].ls;
                    lp.val+=t[lp.pos].val-t[now.pos].val;
                    lp.v=b[t[lp.pos].id].y;
                    hp.push(lp);
                }
                if(t[now.pos].rs){
                    sol lp=now;
                    lp.pos=t[lp.pos].rs;
                    lp.val+=t[lp.pos].val-t[now.pos].val;
                    lp.v=b[t[lp.pos].id].y;
                    hp.push(lp);
                }
            }
        }
        ot(ans);
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
    */
  • 相关阅读:
    iOS 后台运行
    内存管理
    ios -晋级之路 如何去掉tableView多余行的横线
    ios 晋级之路- block深入
    iOS 晋级之路- 调用相机和相册的功能
    iOS开发 --定位
    学习笔记 ios开发 手势
    排序法系列-快速排序法
    计算文本的高度BoundingRectWithSize:options:context
    NSClassFromString的用法
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10878400.html
Copyright © 2011-2022 走看看