题目链接:
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;
}
}