小雨坐地铁 - 图论 - 分层图

http://https://ac.nowcoder.com/acm/problem/26257

  • 题目大意
    小雨所在的城市一共有 m 条地铁线,分别标号为 1 号线,2 号线,……,m 号线。整个城市一共有 n 个车站,编号为 1 ∼n 。其中坐 i 号线需要花费ai的价格,每坐一站就需要多花费 bi的价格。i 号线有 ci个车站,而且这 cic个车站都已知,如果某一站有多条地铁线经过,则可以在这一站换乘到另一条地铁线,并且能多次换乘。现在小雨想从第 s 个车站坐地铁到第 t 个车站,地铁等待时间忽略不计,求最少花费的价格,若不能到达输出 -1 。(地铁是双向的,所以s可能大于t)
  • 样例输入
    5 2 4 1
    2 2 3 1 3 4
    2 1 4 2 3 4 5
  • 样例输出
    6
  • 我的错误想法
    把边标记一下,标记这条边是属于第几号地铁线的,从站点a走到下一个站点b时,设c为乘车到a点的线路编号,d为从a乘车到b的地铁线路,若a!= b,就在更新最短路的时候加上换乘时的费用。错误在于对于样例,从4号站台可以乘1或2号线到达3号站台,在更新最短路的时候,到3号站台的最短路径是乘2号线到达3好站台,然后以这个最短路来更新,实际上最短路径应该是从4好站台一直做1号线知道1号站台,花费为6.
  • 正解
    分层,每一条线路分为一层,对于这条线路上的每一个站点,去建立一个新站台,从旧站台到新站台花费为ai,从新站台到旧站台无花费,然后在新站台上建无向边。最后跑一个最短路。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,m,s,t,c,a,b;
int head[2000010];
int vis[2000010];
ll dis[2000010];
int lp[1010];
struct ty1{
    int st;
    int to;
    int len;
    int next;
}edge[2000010];
struct ty2{
    int num;
    ll dist; 
    bool operator<(const ty2&a) const{
        return dist>a.dist;
    }
};
priority_queue<ty2> q;
int cnt;
void add(int x,int y,int z){
    edge[++cnt].st = x;
    edge[cnt].to = y;
    edge[cnt].len = z;
    edge[cnt].next = head[x];
    head[x] = cnt;
}
int dij(){
    dis[s] = 0;
    q.push({s,0});
    while(!q.empty()){
        auto tp = q.top();
        q.pop();
        int nu = tp.num;
        ll sp = tp.dist;
        if(nu==t) return dis[t];
        for(int i = head[nu];i!=-1;i = edge[i].next){
            int x = edge[i].st;
            int y = edge[i].to;
            int leng = edge[i].len; 
           if(vis[y]||leng+sp>dis[y]) continue;
            dis[y] = leng + sp;
            q.push({y,dis[y]});
           }
        }
    return -1;
}
int main(){
    cin>>n>>m>>s>>t;
    memset(head,-1,sizeof(head));
    cnt = 0;
    int pos = 1001;
    for(int i = 1;i<=m;i++){
        cin>>a>>b>>c;
        for(int j = 1;j<=c;j++){
            cin>>lp[j];
            add(lp[j],pos,a);
            add(pos,lp[j],0);
            if(j>=2){
                add(pos,pos-1,b);
                add(pos-1,pos,b);
            }
            pos++;
        } 
    }
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f3f3f3f,sizeof(dis));
    int ans = dij();
    cout<<ans;
}
posted @   重生之我是菜鸟  阅读(64)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示