zoukankan      html  css  js  c++  java
  • NC26257小雨坐地铁

    最短路分层图

    在最短路中由于各种条件的限制会导致建图的时候会建成分层图

    分层图中将限制条件给消除,变成普通的单元最短路问题。

    链接:https://ac.nowcoder.com/acm/problem/26257
    来源:牛客网

    题目描述

    小雨所在的城市一共有 mmm 条地铁线,分别标号为 1 号线,2 号线,……,m 号线。整个城市一共有 nnn 个车站,编号为 1∼n1 sim n1∼n 。其中坐 i 号线需要花费 aia_iai 的价格,每坐一站就需要多花费 bib_ibi 的价格。i 号线有 cic_ici 个车站,而且这 cic_ici 个车站都已知,如果某一站有多条地铁线经过,则可以在这一站换乘到另一条地铁线,并且能多次换乘。现在小雨想从第 sss 个车站坐地铁到第 ttt 个车站,地铁等待时间忽略不计,求最少花费的价格,若不能到达输出 -1 。(地铁是双向的,所以 sss 可能大于 ttt)

    输入描述:

    第一行输入四个正整数 n,m,s,tn,m,s,tn,m,s,t,分别表示车站个数,地铁线数,起点站和终点站。
    第二行到第 m+1m + 1m+1 行,每行前三个数为 ai,bi,cia_i,b_i,c_iai,bi,ci,分别表示坐 i 号线的价格,i 号线每坐一站多花的价格,i 号线车站个数。接下来 cic_ici 个数,表示 i 号线的每一个车站的编号,单调递增。
    

    输出描述:

    共一行,一个数表示最小花费,若不能到达输出 -1 。
    

    思路:

    在这里插入图片描述

    建立一个如图的分层图,第一层图代表的是第一条线上的各个站点,以此类推。

    第m+1层,也即虚点的一层。将每条线上的每个站点都与对应的虚点的站点相连,虚点->地铁线的边权是a,地铁线->虚点的边权为0,然后建立分层图。

    需要注意的是最后求解距离时要求的是虚点一层的起点->终点。
    求1—>4 ,
    从虚点1出发,到第一条线1,花费为2,
    从1再到3 花费为2
    从第一条线3再到虚点3 花费为0
    虚点3到第二条线3 花费为2
    从第二条线3到4 花费为1
    总花费为7
    此类问题注意初始化问题。

    #include<bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define DOF 0x7f7f7f7f
    #define endl '
    '
    #define mem(a,b) memset(a,b,sizeof(a))
    #define debug(case,x); cout<<case<<"  : "<<x<<endl;
    #define open freopen("ii.txt","r",stdin)
    #define close freopen("oo.txt","w",stdout)
    #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    typedef pair<long long,long long> PII;
    const int maxn = 1e6 + 10;
    int n,m,s,t;
    
    struct edge{
        int next,to,val;
    }edge[maxn];
    int head[maxn],tot=0;
    
    void add(int u,int v,int val){
        edge[++tot].to=v;
        edge[tot].next=head[u];
        edge[tot].val=val;
        head[u]=tot;
    }
    int dis[maxn],vis[maxn];
    priority_queue<pii,vector<pii>,greater<pii> >qp;
    void dij(int src){
        while(!qp.empty())qp.pop();
        dis[src]=0;
        qp.push({0,src});
        while(!qp.empty()){
            pii tt=qp.top();qp.pop();
            int u=tt.second;
            if(vis[u])continue;
            vis[u]=1;
            for(int i=head[u];i;i=edge[i].next){
                if(dis[edge[i].to]>dis[u]+edge[i].val){
                    dis[edge[i].to]=dis[u]+edge[i].val;
                    qp.push({dis[edge[i].to],edge[i].to});
                }
            }
        }
    
    }
    
    int main(){
    //    open;close;
        cin>>n>>m>>s>>t;
        for(int i=0;i<=n*(m+1);++i)dis[i]=INF,head[i]=-1;
        for(int p=1;p<=m;++p){
            int a,b,c,pre;cin>>a>>b>>c;
            for(int i=1;i<=c;++i){
                int x;cin>>x;
                add((p-1)*n+x,n*m+x,0);
                add(n*m+x,(p-1)*n+x,a);
                if(i!=1){
                    add((p-1)*n+pre,(p-1)*n+x,b);
                    add((p-1)*n+x,(p-1)*n+pre,b);
                }
                pre=x;
            }
        }
        dij(m*n+s);
        if(dis[m*n+t]==INF)cout<<-1<<endl;
        else cout<<dis[m*n+t]<<endl;
    
    }
    
    

    参考博客

  • 相关阅读:
    安卓巴士诚招版主,希望各位巴友踊跃加入我们!
    android用户界面之菜单(Menu)教程实例汇总
    360将推出多款360用户特供手机
    安卓巴士最新精选文章,请您查阅
    android用户界面之SeekBar教程实例汇总
    Android OpenGL ES 开发教程小结
    android用户界面之按钮(Button)教程实例汇
    Seleniumwebdriver系列教程(5)————如何定位frame中的元素
    Seleniumwebdriver系列教程(10)————如何智能的等待页面加载完成
    Seleniumwebdriver系列教程(6)————如何捕获弹出窗口
  • 原文地址:https://www.cnblogs.com/waryan/p/13331743.html
Copyright © 2011-2022 走看看