zoukankan      html  css  js  c++  java
  • Bumped!【迪杰斯特拉消边、堆优化】

    Bumped!

     题目链接(点击)

    Peter returned from the recently held ACM ICPC World Finals only to find that his return flight was overbooked and he was bumped from the flight! Well, at least he wasn’t beat up by the airline and he’s received a voucher for one free flight between any two destinations he wishes.

    He is already planning next year’s trip. He plans to travel by car where necessary, but he may be using his free flight ticket for one leg of the trip. He asked for your help in his planning.

    He can provide you a network of cities connected by roads, the amount it costs to buy gas for traveling between pairs of cities, and a list of available flights between some of those cities. Help Peter by finding the minimum amount of money he needs to spend to get from his hometown to next year’s destination!

    Input

    The input consists of a single test case. The first line lists five space-separated integers nn, mm, ff, ss, and tt, denoting the number of cities nn (0<n≤500000<n≤50000), the number of roads mm (0≤m≤1500000≤m≤150000), the number of flights ff (0≤f≤10000≤f≤1000), the number ss (0≤s<n0≤s<n) of the city in which Peter’s trip starts, and the number tt (0≤t<n0≤t<n) of the city Peter is trying to travel to. (Cities are numbered from 00 to n−1n−1.)

    The first line is followed by mm lines, each describing one road. A road description contains three space-separated integers ii, jj, and cc (0≤i,j<n,i≠j0≤i,j<n,i≠j and 0<c≤500000<c≤50000), indicating there is a road connecting cities ii and jj that costs cccents to travel. Roads can be used in either direction for the same cost. All road descriptions are unique.

    Each of the following ff lines contains a description of an available flight, which consists of two space-separated integers uu and vv (0≤u,v<n0≤u,v<n, u≠vu≠v) denoting that a flight from city uu to city vv is available (though not from vv to uu unless listed elsewhere). All flight descriptions are unique.

    Output

    Output the minimum number of cents Peter needs to spend to get from his home town to the competition, using at most one flight. You may assume that there is a route on which Peter can reach his destination.

    Sample Input 1 Sample Output 1
    8 11 1 0 5
    0 1 10
    0 2 10
    1 2 10
    2 6 40
    6 7 10
    5 6 10
    3 5 15
    3 6 40
    3 4 20
    1 4 20
    1 3 20
    4 7
    
    45
    

    Sample Input 2

    Sample Output 2
    8 11 1 0 5
    0 1 10
    0 2 10
    1 2 10
    2 6 40
    6 7 10
    5 6 10
    3 5 15
    3 6 40
    3 4 20
    1 4 20
    1 3 30
    4 7

    思路:

    开始只学过 普通的迪杰斯特拉+链式前向星 对这个题开始就是想先跑一遍当做最小值 然后把f张机票 每次使用一张再求出最短路 最后果断T了

    没办法比赛完去学堆优化 其实和普通的没多大差别 只是使用了优先队列

    学会之后就接着做这个题 结果卡在 23/25 了 以为是链式前向星不可以消边 就感觉用迪杰斯特拉消边不对(我也查了资料说vector和邻接矩阵方便消边)可vector 不会 所以就接着学

    学完提交还是卡23了 就知道肯定是那个地方个人习惯问题

    找了好长时间终于发现 是const int INF时候INF 超 int 了 (下次肯定好好审一审它)

    顿时感觉……

    不过挺开心的 还学会了vector存图 迪杰斯特拉堆优化 还自己把链式前向星的消边搞了出来

    有时间就再写一下vector

    AC代码:

    1.链式前向星+迪杰斯特拉堆优化

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    using namespace std;
    typedef long long LL;
    const int MAX=1e6;
    const LL MAX1=1e10;
    LL n;
    LL head[MAX+5],flag[MAX+5],ans=0;
    LL dis[MAX+5],vis[MAX+5];
    struct note{
        LL to;
        LL len;
        LL next;
    }edge[MAX+5];
    struct note1{
        LL x;
        LL y;
    }edge1[MAX+5];
    struct node{
        LL to,len;
        node(LL a,LL b){
            to=b;
            len=a;
        }
        friend bool operator < (node a,node b){ ///是<而不是< node
            return a.len>b.len;
        }
    };
    void addnode(LL u,LL v,LL w)
    {
        edge[ans].to=v;
        edge[ans].len=w;
        edge[ans].next=head[u];
        flag[u]=head[u];
        head[u]=ans++;
    }
    void allbegin()
    {
        memset(head,-1,sizeof(head));
        ans=0;
    }
    priority_queue<node>q;
    void diji(LL s)
    {
        for(LL i=0;i<=n;i++){  ///不能忘记将diji的数组初始化
            dis[i]=MAX1;
            vis[i]=0;
        }
        while(!q.empty()){
            q.pop();
        }
        dis[s]=0;
        q.push(node(0,s));
        while(!q.empty()){
            node num=q.top();
            q.pop();  ///用完后把最上层去掉
            if(vis[num.to]){
                continue;
            }
            vis[num.to]=1;
            for(LL i=head[num.to];~i;i=edge[i].next){
                if((dis[edge[i].to]>dis[num.to]+edge[i].len)&&edge[i].len!=MAX1+1){
                    dis[edge[i].to]=dis[num.to]+edge[i].len;  ///copy完改符号
                    q.push(node(dis[edge[i].to],edge[i].to));///将这个to点对应的len重新放入队列中
                }
            }
        }
    }
    int main()
    {
        LL m,f,a1,a2;
        scanf("%lld%lld%lld%lld%lld",&n,&m,&f,&a1,&a2);
        allbegin();
        for(LL i=0;i<m;i++){
            LL u,v,w;
            scanf("%lld%lld%lld",&u,&v,&w);
            addnode(u,v,w);
            addnode(v,u,w);
        }
        for(LL i=0;i<f;i++){
            LL u,v;
            scanf("%lld%lld",&edge1[i].x,&edge1[i].y);
        }
        diji(a1);
        LL minn=dis[a2];
        for(LL i=0;i<f;i++){
            diji(edge1[i].x);
            LL num=dis[edge1[i].y];
            addnode(edge1[i].x,edge1[i].y,0);
            diji(a1);
            if(minn>dis[a2]){
                minn=dis[a2];
            }
            if(num==MAX1){
                edge[ans-1].len=MAX1+1;
            }
            else{
                edge[ans-1].len=num;
            }
        }
        printf("%lld
    ",minn);
        return 0;
    }

    2、vector+链式前向星堆优化

    #include<stdio.h>
    #include<vector>
    #include<queue>
    using namespace std;
    typedef long long LL;
    const LL INF=1e10;
    const int MAX=150010;
    
    int n;
    struct node{
        int to;
        LL len;
        node(int _to=0,LL _len=0):to(_to),len(_len){
    
        }
        bool operator<(const node &r)const{
            return len>r.len;
        }
    };
    struct note{
        int to;
        LL len;
        note(int _to=0,LL _len=0):to(_to),len(_len){}
    };
    int vis[MAX+5];
    LL dis[MAX+5];
    vector<note>v[MAX+5];
    void diji(int s)
    {
        for(int i=0;i<MAX+5;i++){
            vis[i]=0,dis[i]=INF;
        }
        priority_queue<node>q;
        while(!q.empty()){
            q.pop();
        }
        dis[s]=0;
        q.push(node(s,0));
        node num;
        while(!q.empty()){
            num=q.top();
            q.pop();
            int u=num.to;
            if(vis[u]){
                continue;
            }
            vis[u]=1;
            for(int i=0;i<v[u].size();i++){
                int to=v[u][i].to;
                LL len=v[u][i].len;
                if(!vis[to]&&dis[to]>dis[u]+len){
                    dis[to]=dis[u]+len;
                    q.push(node(to,dis[to]));
                }
            }
        }
    }
    int main()
    {
        int m,f,a1,a2;
        scanf("%d%d%d%d%d",&n,&m,&f,&a1,&a2);
        for(int i=0;i<m;i++){
            int u;
            node num;
            scanf("%d%d%lld",&u,&num.to,&num.len);
            v[u].push_back(note(num.to,num.len));
            v[num.to].push_back(note(u,num.len));
        }
        diji(a1);
        LL minn=dis[a2];
        for(int i=0;i<f;i++){
            int u;
            node num;
            scanf("%d%d",&u,&num.to);
            num.len=0;
            v[u].push_back(note(num.to,num.len));
            diji(a1);
            minn = min(minn,dis[a2]);
            v[u].erase(v[u].end()-1);
        }
        printf("%lld
    ",minn);
        return 0;
    }
    
  • 相关阅读:
    linux中你会新建复制移动删除文件或目录吗?三分钟搞懂【文件管理】
    从此英语渣渣也能看懂man手册-【linux man手册汉化安装使用教程】
    你真的会用ls命令吗?--文件管理命令(ls命令详解)
    Python算法系列—深度优先遍历算法【二叉树】
    Python算法系列-单词匹配模式【hash练习】
    abp 从4.3升级到5.4 从入门到放弃
    ABP core2.2错误笔记2,持续更新
    echart报错: Component series.XXX not exists. Load it first
    单例模式MQTT服务为什么会重复收到消息
    在ABP core中使用RabbitMq
  • 原文地址:https://www.cnblogs.com/ldu-xingjiahui/p/12407446.html
Copyright © 2011-2022 走看看