小雨坐地铁--[最短路分层建图+虚点]

也是第一次接触这种分层建图的最短路
思路:由题目我们可以知道某些站点是可以连接好几条地铁线路的,那么对于每条地铁线路我们可以把他当成一幅图来算。当然图是个无向图,所以要加两次边。

add(i*n+x,i*n+pre,b); //乘i的话就是说把他建在第i层,这个pre是记录上一个点的位置。 add(i*n+pre,i*n+x,b); 

处理换乘时的操作
利用到我们刚刚所说的虚点

add(x,i*n+x,a); //从虚点到地铁线上需要花费,花费坐这条线的价格 //也就是题中(坐i号线需要花费a[i]的价格)  add(i*n+x,x,0); //从地铁线上到虚点花费为0 

根据题目中样例建成的图就是(图来源于大佬博客)https://blog.nowcoder.net/n/149da7cef2d8451d8ff1e319ebc6e663

接下来的过程就跟最短路模板题一样了
代码:

#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <math.h>
#include <string>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#define maxn  1000010
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int mod = 1000007;
using namespace std;
struct wazxy{
    int to,w,next;
}edge[maxn];
struct node{
    int n,dis;
    node(int a,int b){n=a,dis=b;}
    bool operator <(const node & a)const
    {return dis>a.dis;}
};
int dis[maxn];
int head[maxn];
int cnt=0,n,m,s,t;
bool visited[maxn];
void init(){
    memset(head,-1,sizeof(head));
    memset(visited,false,sizeof(visited));
    memset(dis,MaxN,sizeof(dis));
}
void add(int u,int v,int w){
    edge[cnt].w=w;
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
void dij(int x){
    dis[x]=0;
    priority_queue<node> q;
    q.push(node(x,0));
    while(!q.empty()){
        node temp=q.top();
        q.pop();
        if(visited[temp.n]) continue;
        visited[temp.n]=true;
        for(int i=head[temp.n];~i;i=edge[i].next){
            int v=edge[i].to;
            int w=edge[i].w;
            if(visited[v]) continue;
            if(dis[v]>temp.dis+w){
                dis[v]=temp.dis+w;
                q.push(node(v,dis[v]));
            }
        }
    }
}
int main()
{
    cin>>n>>m>>s>>t;
    init();
    for(int i=1;i<=m;i++){
        int a,b,c,x;
        scanf("%d%d%d",&a,&b,&c);
        int pre=-1;
        while(c--){
            cin>>x;
            if(pre!=-1){
                add(i*n+x,i*n+pre,b);  //乘i的话就是说把他建在第i层
                add(i*n+pre,i*n+x,b);
            }
            add(x,i*n+x,a);
            add(i*n+x,x,0);
            pre=x;
        }
    }
    dij(s);
    if(dis[t]==MaxN) cout<<"-1"<<endl;
    else cout<<dis[t]<<endl;
    return 0;
}



题解 文章被收录于专栏

主要写一些题目的题解

全部评论

相关推荐

11-24 00:11
已编辑
广东工业大学 算法工程师
避雷深圳&nbsp;&nbsp;yidao,试用期&nbsp;6&nbsp;个月。好嘛,试用期还没结束,就直接告诉你尽快找下一家吧,我谢谢您嘞
牛客75408465号:笑死,直属领导和 hr 口径都没统一,各自说了一些离谱的被裁理由,你们能不能认真一点呀,哈哈哈哈哈😅😅😅
点赞 评论 收藏
分享
一个菜鸡罢了:哥们,感觉你的简历还是有点问题的,我提几点建议,看看能不能提供一点帮助 1. ”新余学院“别加粗,课程不清楚是否有必要写,感觉版面不如拿来写一下做过的事情,教育经历是你的弱势就尽量少写 2. “干部及社团经历”和“自我评价”删掉 3. 论文后面的“录用”和“小修”啥的都删掉,默认全录用,问了再说,反正小修毕业前肯定能发出来 4. 工作经验和研究成果没有体现你的个人贡献,着重包装一下个人贡献
点赞 评论 收藏
分享
10-11 17:45
门头沟学院 Java
走吗:别怕 我以前也是这么认为 虽然一面就挂 但是颇有收获!
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务