• J 小雨坐地铁(分层最短路)


    链接:https://ac.nowcoder.com/acm/contest/949/J
    来源:牛客网

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

    输入描述:

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

    输出描述:

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

    输入

    5 2 1 4
    2 2 3 1 3 5
    2 1 4 2 3 4 5

    输出

    7

    说明

    坐 1 号线:花费 2;

    13:花费 2;

    换乘 2 号线:花费 2;

    34:花费 1;

    所以最小总花费为 7 。

    备注:

    1n1000,1m500,1s,tn

    1ai,bi100,1cin,mi=1ci105

    思路:每条地铁线路可以看做一层图,一层一层图之间正常建边即可。每层之间可能是相连的,怎么处理?
    对应每个车站 设立一个虚点。只要每层的车站与对应的虚点连接即可。 连接方式是虚点连向车站的花费是上地铁的钱(或转地铁的钱)。
    而车站连接虚点花费为0,这样达到中转的效果。


    设立虚点的好处:不用根据层与层间连边,这样每层都要连,就要m*m*n条边,而设立虚点只要n*m*2。
    计算也方便,直接从s的虚点可是找t的虚点的最短路就是结果。不设虚点,要对应每个车站s的地铁到每个车站t的地铁求最短路。

    代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn=2100;
    struct node{
        int u,v,w,next;
    }e[maxn*maxn]; 
    int head[maxn*maxn],n,m,s,t,cnt;
    int a[maxn],b[maxn],d[maxn*maxn],vis[maxn*maxn];
    void add(int u,int v,int w)
    {
        e[cnt]={u,v,w,head[u]};
        head[u]=cnt++;
    }
    
    void spfa(int st)//spfa
    {
        d[st]=0;
        queue<int> q;
        q.push(st);
        vis[st]=1;
        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;
                int w=e[i].w;
                if(d[v]>d[u]+w)
                {
                    d[v]=d[u]+w;
                    if(!vis[v])
                    {
                        vis[v]=1;
                        q.push(v);
                    }
                }
            } 
        }        
    }
    
    int main()
    {
        int num,x,last;
        cnt=0;
        memset(head,-1,sizeof(head));
        memset(d,0x3f,sizeof(d));
        scanf("%d%d%d%d",&n,&m,&s,&t);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a[i],&b[i],&num);
            for(int j=1;j<=num;j++)
            {
                scanf("%d",&x);
                if(j!=1)
                {
                    add((i-1)*n+x,(i-1)*n+last,b[i]);//同一条线车站相连 
                    add((i-1)*n+last,(i-1)*n+x,b[i]);
                }
                add((i-1)*n+x,n*m+x,0);//与每个虚点相连 
                add(n*m+x,(i-1)*n+x,a[i]);
                last=x;//记录之前的车站 
            }
        }
        spfa(n*m+s);//最短路 
        if(d[n*m+t]<inf)
            printf("%d
    ",d[n*m+t]);
        else
            printf("-1
    ");
        return 0;
    } 
  • 相关阅读:
    我们都可以把它放 Sidecar 容器中,这样微服务具备了 Super power,一种超能力
    DP 状态 DP 转移方程 动态规划解题思路
    完全二叉树 原因 完全二叉树最后一层节点靠左的原因
    延时任务最佳实践方案总结
    b+ 树 只存储 索引
    埋点质量保障体系建设
    linux命令重定向>、>>、 1>、 2>、 1>>、 2>>、 <
    卡特兰数
    python 使用函数名的字符串调用函数(4种方法)_black-heart的专栏-CSDN博客 https://blog.csdn.net/mrqingyu/article/details/84403924
    12 | 服务注册与发现如何满足服务治理
  • 原文地址:https://www.cnblogs.com/xiongtao/p/11183255.html
Copyright © 2020-2023  润新知