HDU - 2680 【多源最短路 Bellman-Fordl模板】

题目描述:

One day , Kiki wants to visit one of her friends. As she is liable to carsickness , she wants to arrive at her friend’s home as soon as possible . Now give you a map of the city’s traffic route, and the stations which are near Kiki’s home so that she can take. You may suppose Kiki can change the bus at any station. Please find out the least time Kiki needs to spend. To make it easy, if the city have n bus stations ,the stations will been expressed as an integer 1,2,3…n.

Input

There are several test cases. 
Each case begins with three integers n, m and s,(n<1000,m<20000,1=<s<=n) n stands for the number of bus stations in this city and m stands for the number of directed ways between bus stations .(Maybe there are several ways between two bus stations .) s stands for the bus station that near Kiki’s friend’s home. 
Then follow m lines ,each line contains three integers p , q , t (0<t<=1000). means from station p to station q there is a way and it will costs t minutes . 
Then a line with an integer w(0<w<n), means the number of stations Kiki can take at the beginning. Then follows w integers stands for these stations. 

Output

The output contains one line for each data set : the least time Kiki needs to spend ,if it’s impossible to find such a route ,just output “-1”.

Sample Input

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

Sample Output

1
-1

题目大意:

给定一个无向图,给定终点,以及多个起点,求任意起点到终点最短路径。

解题思路:

。。

给你!神仙spfa模板!https://blog.csdn.net/sodacoco/article/details/83865941

现在明白了“图论只会套模板”是什么意思了,我连模板都不会套,,对着Dijkstra弄了半天,以为是单源最短路,怎么都觉得好麻烦,定睛再一看,这不是多源最短路吗?!又去套多源最短路的模板,样例过了,思路绝对没问题【模板没套错】,然后RunTime了,,等等,RunTime,RunTime是数组越界?改了数组大小,三重循环正好TLE,WTFunny。所以模板又套错了,看看自己写的神仙模板Bellman-Fordl,就是spfa,恩,整理的狗屁模板啊,模板会规定好起点吗?【心塞*3】

样例中第一个样例如图:

找了找大佬的模板:https://www.cnblogs.com/weiyuan/p/5697899.html

代码实现:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define M 1009
#define INF 0x3f3f3f3f
struct edge
{
    int to,w;//保存边的信息,包括边的终点以及权值
};
int dis[M];  //最短距离的估计值(当前该点的最短距离)
bool inq[M]; //标记该点是否在队列之中
vector<edge> g[M]; //利用一个vector保存,g[i]表示以i为起点的所有边的信息
int n,m,ee;
void spfa(int u)
{
    for(int i = 0;i <= n;i++) //初始化
    {
        dis[i] = INF; //将估计值都初始化为INF
        inq[i] = false; //初始化为不在队列中
    }
    dis[u] = 0; //起点的估计值直接就是0
    inq[u] = true; //加入队列并进行标记
    queue<int> q;
    q.push(u);
    while(!q.empty())
    {
        u = q.front();
        inq[u] = false;
        q.pop();
        for(int i = 0;i < g[u].size();i++)
        {
            int v = g[u][i].to; //找出这条边对应的终点
            int w = g[u][i].w;  //这条边对应的权值
            if(dis[v] > dis[u]+w) //如果终点的最短距离比起点的最短距离加上这条边的权值那么就更新
            {
                dis[v] = dis[u]+w;
                if(!inq[v]) //如果v点的最短距离有所更新并且不在队列中,就将其加入队列。
                {           //否则就不需要重复加入队列增加不必要的操作。
                    inq[v] = true;  //加入队列并标记
                    q.push(v);
                }
            }
        }
    }
}
int main()
{
    while(scanf("%d %d %d",&n,&m,&ee)==3)
    {
        for(int i = 0;i <= n;i++) //清空vector避免多kase相互影响
            g[i].clear();
        for(int i = 0;i < m;i++)
        {
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            edge e;
            e.to = b;e.w = c;
            g[a].push_back(e);
            //e.to = a;
            //g[b].push_back(e);  //题目中有说从a到b有这条路,并不是双向的。
        }
        int s;
        scanf("%d",&s);
        for(int i = 0;i < s;i++)
        {
            int a;
            scanf("%d",&a);
            edge e;
            e.to = a; e.w = 0;
            g[0].push_back(e); //将家里到起点的权值设为0
            //e.to = 0;
            //g[a].push_back(e);  //从起点到家里是否有路其实无关紧要,因为思考一下有路的话 起点到起点也是0,所以根本不影响结果
        }
        spfa(0);
        //printf("debug-----%d\n",dis[ee]);
        if(dis[ee]==INF)
            printf("-1\n");
        else
            printf("%d\n",dis[ee]);
    }
    return 0;
}

果然是简洁又通用,我得看明白讲解算法样例和算法模板的区别,晚安!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值