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;
    }
    
  • 相关阅读:
    IP,子网,子网掩码,网关,DNS到底都是啥(二)
    (能被11整除的数的特征)The shortest problem --hdu
    (匹配 匈牙利)棋盘游戏 -- Hdu --1281
    (匹配)Courses -- hdu --1083
    (匹配 最小路径覆盖)Air Raid --hdu --1151
    (匹配)The Accomodation of Students --HDU --2444
    (匹配)Fire Net --hdu --1045
    (二分匹配 模板)过山车 -- hdu --2063
    (连通图 ) Redundant Paths --POJ --3177
    (二分匹配 模板 KM)奔小康赚大钱--hdu--2255
  • 原文地址:https://www.cnblogs.com/ldu-xingjiahui/p/12407446.html
Copyright © 2011-2022 走看看