zoukankan      html  css  js  c++  java
  • E-免费的飞机

    题目链接:https://ac.nowcoder.com/acm/contest/699/E

    题目意思:有n个飞机场,给你起点s,终点e,有m种带权的无向边飞机线路。有k个线路,可以从中选一个免费飞行。问是否使用免费飞机票,并输出最短路花费。

    思路:

    1.先建普通飞机线路,算出最短路。再每一条免费线路重新算一次最短路,再判断是否比之前小。

    spfa写法:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    struct node{
        int u,v,w,next;
    }e[2050];
    int head[1050],vis[1050],d[1050];
    int st,ed,n,m,k,cnt;
    int from[1050],to[1050],val[1050];
    void add(int u,int v,int w)
    {
        e[cnt].u=u;
        e[cnt].v=v;
        e[cnt].w=w;
        e[cnt].next=head[u];
        head[u]=cnt++;
    }
    
    void spfa()//spfa算最短路 
    {
        memset(d,0x3f,sizeof(d));
        memset(vis,0,sizeof(vis));
        queue<int> q;
        vis[st]=1;
        d[st]=0;
        q.push(st);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i!=-1;i=e[i].next)
            {
                int v=e[i].v;
                if(d[v]>d[u]+e[i].w)
                {
                    d[v]=d[u]+e[i].w;
                    if(!vis[v])
                    {
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    
    int main()
    {
        int u,v,w;
        cnt=0;
        memset(head,-1,sizeof(head));
        std::ios::sync_with_stdio(false);
        cin>>n>>st>>ed>>m;
        for(int i=1;i<=m;i++)
        {
            cin>>from[i]>>to[i]>>val[i];
            add(from[i],to[i],val[i]);
            add(to[i],from[i],val[i]);
        }
        spfa();
        int ans=d[ed];//记录没有用免费机票的最短路 
        int anss=inf;
        cin>>k;
        for(int i=0;i<k;i++)
        {
            cin>>u>>v;
            add(u,v,0);
            add(v,u,0);
            spfa();//每条免费线路算一次最短路 
            anss=min(anss,d[ed]);
            cnt=0;
            memset(head,-1,sizeof(head));//记得初始化 
            for(int i=1;i<=m;i++)
            {
                add(from[i],to[i],val[i]);
                add(to[i],from[i],val[i]);
            }
        }
        if(ans==anss)
            cout<<"No"<<endl<<ans<<endl;
        else
            cout<<"Yes"<<endl<<anss<<endl;
        return 0;
    }
    View Code

    dijkstra写法:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define inf 0x3f3f3f3f
    #include<queue>
    using namespace std;
    typedef long long ll;
    struct node{
        int u,v,w,next;
    }e[2050];
    struct nd{
        int id;
        int dis;
        bool operator <(const nd &a)const{
            return a.dis<dis;
        }
    };
    int head[1050],vis[1050],d[1050];
    int st,ed,n,m,k,cnt;
    int from[1050],to[1050],val[1050];
    void add(int u,int v,int w)
    {
        e[cnt].u=u;
        e[cnt].v=v;
        e[cnt].w=w;
        e[cnt].next=head[u];
        head[u]=cnt++;
    }
    void dij()//优先队列优化 
    {
        priority_queue<nd> q;
        memset(d,0x3f,sizeof(d));
        memset(vis,0,sizeof(vis));
        d[st]=0;
        while(!q.empty())
            q.pop();
        q.push({st,0});
        while(!q.empty())
        {
            nd t=q.top();
            q.pop();
            int u=t.id;
            if(vis[u])
                continue;
            vis[u]=1;
            for(int i=head[u];i!=-1;i=e[i].next)
            {
                int v=e[i].v;
                if(!vis[v]&&d[v]>d[u]+e[i].w)
                {
                    d[v]=d[u]+e[i].w;
                    q.push({v,d[v]});
                }
            }
        }
    }
    
    int main()
    {
        int u,v,w;
        cnt=0;
        memset(head,-1,sizeof(head));
        std::ios::sync_with_stdio(false);
        cin>>n>>st>>ed>>m;
        for(int i=1;i<=m;i++)
        {
            cin>>from[i]>>to[i]>>val[i];
            add(from[i],to[i],val[i]);
            add(to[i],from[i],val[i]);
        }
        dij();
        int ans=d[ed];
        int anss=inf;
        cin>>k;
        for(int i=0;i<k;i++)
        {
            cin>>u>>v;
            add(u,v,0);
            add(v,u,0);
            dij();
            anss=min(anss,d[ed]);
            cnt=0;
            memset(head,-1,sizeof(head));
            for(int i=1;i<=m;i++)
            {
                add(from[i],to[i],val[i]);
                add(to[i],from[i],val[i]);
            }
        }
        if(ans==anss)
            cout<<"No"<<endl<<ans<<endl;
        else
            cout<<"Yes"<<endl<<anss<<endl;
        return 0;
    }
    View Code

    2.开始就算出起点到所有点的最短距离和终点到所有点的最短路,在每次免费线路直接判断是否小就可以。因为是无向边,可以直接算终点到所有点的距离,如果是有向边,只要反向建边再算即可。这个思路只算了两次最短路,明显是上面快很多的。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define inf 0x3f3f3f3f
    #include<queue>
    using namespace std;
    typedef long long ll;
    struct node{
        int u,v,w,next;
    }e[2050];
    struct nd{
        int id;
        int dis;
        bool operator <(const nd &a)const{
            return a.dis<dis;
        }
    };
    int head[1050],vis[1050],d[1050][1050];
    int st,ed,n,m,k,cnt;
    void add(int u,int v,int w)
    {
        e[cnt].u=u;
        e[cnt].v=v;
        e[cnt].w=w;
        e[cnt].next=head[u];
        head[u]=cnt++;
    }
    void dij(int start)
    {
        priority_queue<nd> q;
        memset(vis,0,sizeof(vis));
        d[start][start]=0;
        while(!q.empty())
            q.pop();
        q.push({start,0});
        while(!q.empty())
        {
            nd t=q.top();
            q.pop();
            int u=t.id;
            if(vis[u])
                continue;
            vis[u]=1;
            for(int i=head[u];i!=-1;i=e[i].next)
            {
                int v=e[i].v;
                if(!vis[v]&&d[start][v]>d[start][u]+e[i].w)
                {
                    d[start][v]=d[start][u]+e[i].w;
                    q.push({v,d[start][v]});
                }
            }
        }
    }
    
    int main()
    {
        int u,v,w,flag=0;
        cnt=0;
        memset(head,-1,sizeof(head));
        std::ios::sync_with_stdio(false);
        cin>>n>>st>>ed>>m;
        for(int i=1;i<=m;i++)
        {
            cin>>u>>v>>w;
            add(u,v,w);
            add(v,u,w);
        }
        memset(d,0x3f,sizeof(d));
        dij(st);//算出起点到所有点的最短路。 
        int ans=d[st][ed];
        dij(ed);//算出终点到所有点的最短路 
        int anss=inf;    
    //    for(int i=1;i<=n;i++)
    //        cout<<i<<' '<<d[st][i]<<' '<<d[ed][i]<<endl;
        cin>>k;
    
        for(int i=0;i<k;i++)
        {
            cin>>u>>v;
            if(ans>d[st][u]+d[ed][v]||ans>d[st][v]+d[ed][u])//判断是否用免费机票 
            {
                anss=min(anss,min(d[st][u]+d[ed][v],d[st][v]+d[ed][u]));
                flag=1;
            }    
        }
        if(!flag)
            cout<<"No"<<endl<<ans<<endl;
        else
            cout<<"Yes"<<endl<<anss<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    【已解决】github中git push origin master出错:error: failed to push some refs to
    好记心不如烂笔头,ssh登录 The authenticity of host 192.168.0.xxx can't be established. 的问题
    THINKPHP 5.0目录结构
    thinkphp5.0入口文件
    thinkphp5.0 生命周期
    thinkphp5.0 架构
    Django template
    Django queryset
    Django model
    Python unittest
  • 原文地址:https://www.cnblogs.com/xiongtao/p/10744889.html
Copyright © 2011-2022 走看看