1.题目
题目链接
2.解决方法
当要求多个源点到汇点的最短路径,可以将这些源点添加一个虚拟的前驱结点作为虚拟源点;问题转化为求从虚拟源点的单源最短路径问题。
3.代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN=1010,MAXM=2e5+1e4+10,INF=0x3f3f3f3f;
int n,m,s,num;
int dist[MAXN];
bool st[MAXN];
int e[MAXM],h[MAXN],ne[MAXM],w[MAXM],idx;
//当涉及到多个起点到其他所有点的最短路径时,可以通过设置一个虚拟源点解决问题,这个虚拟源点与所有起点邻接且边权为0
//虚拟源点到所有点的最短路径也就是所有起点到其他点的最短路径最小值
void add(int a,int b,int c)
{
e[idx]=b;
ne[idx]=h[a];
w[idx]=c;
h[a]=idx++;
}
int spfa()
{
memset(dist,0x3f,sizeof(dist));
dist[0]=0;//虚拟源点作为起点
queue<int> q;
q.push(0);
st[0]=true;
while(!q.empty()){
int t=q.front();
q.pop();
st[t]=false;
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
if(dist[j]>dist[t]+w[i]){
dist[j]=dist[t]+w[i];
if(!st[j]){
q.push(j);
st[j]=true;
}
}
}
}
if(dist[s]>=INF/2) return -1;
return dist[s];
}
int main(void)
{
while(~scanf("%d%d%d",&n,&m,&s)){
memset(h,-1,sizeof(h));
idx=0;
for(int i=0;i<m;i++){
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
cin>>num;
for(int i=0;i<num;i++){
int p;
cin>>p;
add(0,p,0);
}
printf("%d\n",spfa());
}
return 0;
}