hdu2680 Choose the best route(spfa求最短路模板题)

题目链接:

http://acm.split.hdu.edu.cn/viewcode.php?rid=22429291

题目大意:

给你n个车站,每条路的收费为c,给你几个你可以出发的车站,求出到终点站的最短路大小。

题目思路:

spfa跑一遍最短路,待解决的一个点就是你不知道起点,那么我就可以建立一个超级起点,超级起点到可出发车站的权值为0,然后从超级起点跑一遍最短路即可。

代码:

#include <bits/stdc++.h>
using namespace std;
#define M 1009
#define INF 0x3f3f3f3f

//在这里M代表点的最大值
struct edge
{
    int to,w;//保存边的信息,包括边的终点以及权值
};
int dis[M];  //最短距离的估计值(当前该点的最短距离),跑完spfa后,保存的是起点到该点的最短距离
bool inq[M]; //标记该点是否在队列之中
vector<edge> g[M]; //利用一个vector保存,g[i]表示以i为起点的所有边的信息
int n,m,ee;//n是点 m是边 ee是终点
void spfa(int u)//从起点跑spfa,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)){
        for(int i=0;i<=n;i++) g[i].clear();

        for(int i=1;i<=m;i++){
            int p,q,t;
            scanf("%d%d%d",&p,&q,&t);
                edge e;
                e.to=q;e.w=t;
                g[p].push_back(e);

        }
        int s;
        scanf("%d",&s);
        for(int i=1;i<=s;i++){
            int x;scanf("%d",&x);
            edge e;
            e.to=x;e.w=0;
            g[0].push_back(e);
        }
        spfa(0);
        if(dis[ee]==INF) cout<<"-1"<<endl;
        else cout<<dis[ee]<<endl;
    }
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值