acwing 1137 选择最佳线路 【任选起点->固定终点 问题】【假设虚拟源点经典题目】【特殊而非多源多汇模型】

1137. 选择最佳线路

有一天,琪琪想乘坐公交车去拜访她的一位朋友。

由于琪琪非常容易晕车,所以她想尽快到达朋友家。

现在给定你一张城市交通路线图,上面包含城市的公交站台以及公交线路的具体分布。

已知城市中共包含 nn 个车站(编号11~nn)以及 mm 条公交线路。

每条公交线路都是 单向的,从一个车站出发直接到达另一个车站,两个车站之间可能存在多条公交线路。

琪琪的朋友住在 ss 号车站附近。

琪琪可以在任何车站选择换乘其它公共汽车。

请找出琪琪到达她的朋友家(附近的公交车站)需要花费的最少时间。

输入格式

输入包含多组测试数据。

每组测试数据第一行包含三个整数 n,m,sn,m,s,分别表示车站数量,公交线路数量以及朋友家附近车站的编号。

接下来 mm 行,每行包含三个整数 p,q,tp,q,t,表示存在一条线路从车站 pp 到达车站 qq,用时为 tt。

接下来一行,包含一个整数 ww,表示琪琪家附近共有 ww 个车站,她可以在这 ww 个车站中选择一个车站作为始发站。

再一行,包含 ww 个整数,表示琪琪家附近的 ww 个车站的编号。

输出格式

每个测试数据输出一个整数作为结果,表示所需花费的最少时间。

如果无法达到朋友家的车站,则输出 -1。

每个结果占一行。

数据范围

n≤1000,m≤20000n≤1000,m≤20000,
1≤s≤n1≤s≤n,
0<w<n0<w<n,
0<t≤10000<t≤1000

输入样例:

5 8 5
1 2 2
1 5 3
1 3 4
2 4 7
2 5 6
2 3 5
3 5 1
4 5 1
2
2 3
4 3 4
1 2 3
1 3 4
2 3 2
1
1

输出样例:

1
-1
难度:简单
时/空限制:1s / 64MB
总通过数:3964
总尝试数:8637
来源:HDOJ
算法标签

acwing 137 矩阵距离 (多源BFS)

与 acwing 昂贵的聘礼都是此类题目

本题看似多个起点,是个多源问题,

但是由于起点任选,决定了它不是个普通的多源问题,

应该靠虚拟源点实现单源最短路

#include <bits/stdc++.h>
using namespace std;
const int N=1010,M=20010,INF=0x3f3f3f3f;
int n,m,s;
int h[N],ne[M],w[M],e[M],idx;
int dis[N];
int q[N];  //循环队列
bool st[N];
void add(int a,int b,int c)
{
    e[idx]=b;
    w[idx]=c;
    ne[idx]=h[a];
    h[a]=idx++;
}

void spfa()
{
    int ww;
    scanf("%d",&ww);

    memset(dis,0x3f,sizeof dis);
    int hh=0,tt=0;
    //本来是 hh=0,tt=1 ,由于此处要入队多个点,统一用++tt
    while(ww--)  //从ww个起点中任选起点
    {
        int u;
        scanf("%d",&u);
        dis[u]=0;
        q[tt++]=u;
        st[u]=true;
    }

    while(hh!=tt)
    {
        int t=q[hh++];
        if(hh==N) hh=0;

        st[t]=false;

        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(dis[j]>dis[t]+w[i])
            {
                dis[j]=dis[t]+w[i];
                if(!st[j])
                {
                    q[tt++]=j;
                    if(tt==N) tt=0;
                    st[j]=true;
                }
            }
        }
    }



}


int main()
{
    while(scanf("%d%d%d",&n,&m,&s)!=-1)
    {
        memset(h,-1,sizeof h);
        idx=0;

        while(m--)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
        }

        spfa();

        if(dis[s]==0x3f3f3f3f) dis[s]=-1;
        printf("%d\n",dis[s]);
    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值