题意: 第一行三个数n m t 代表 n个点 m条边 终点是t 接下来m行每行三个数 u v d 代表从u 到 v 距离为 d 再一行 一个数x 代表有x个起点 接下来一行有x个数 代表这x个起点 让你求从这些起点到终点的最短路 没有的话输出-1
思路:其实这道题看似多个起点 要求多次最短路 但是如果加一个虚节点 将多个起点连起来 这不就是经典的单源最短路了吗 - -
这题我用的是SPFA 但是速度居然没有Dijkstra快!! 的确SPFA很不稳定啊...
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define REP(i, a, b) for( int i = a; i < b; i++ )
#define CLR(a, x) memset( a, x, sizeof a )
const int maxn = 1000 + 10;
const int maxe = 20000 + 10;
const int INF = 1e9;
struct Edge{
int v, d;
int next;
Edge(){}
Edge(int v, int d, int next) : v(v), d(d), next(next){}
};
struct SPFA{
int top, cntE, n;
int Head[maxn], vis[maxn], cnt[maxn], STACK[maxn], dist[maxn];
Edge edge[maxe];
void init(int n){
this -> n = n;
CLR(Head, -1);
CLR(vis, 0);
cntE = top = 0;
}
void add(int u, int v, int d){
edge[cntE] = Edge(v, d, Head[u]);
Head[u] = cntE++;
}
bool spfa(int s){
CLR(vis, 0);
CLR(cnt, 0);
vis[s] = cnt[s] = 1;
STACK[top++] = s;
REP(i, 0, n) dist[i] = INF;
dist[s] = 0;
while(top){
int u = STACK[--top];
vis[u] = 0;
for(int i = Head[u]; ~i; i = edge[i].next){
int v = edge[i].v;
if(dist[v] > dist[u] + edge[i].d){
dist[v] = dist[u] + edge[i].d;
if(!vis[v]){
vis[v] = 1;
STACK[top++] = v;
if(++cnt[v] > n) return false;
}
}
}
}
return true;
}
}Spfa;
int n, m, T, u, v, d;
void solve(){
Spfa.init(n + 1);
REP(i, 0, m){
scanf("%d%d%d", &u, &v, &d);
Spfa.add(u, v, d);
}
scanf("%d", &u);
while(u--){
scanf("%d", &v);
Spfa.add(0, v, 0);
}
if(Spfa.spfa(0)){
if(Spfa.dist[T] < INF) printf("%d\n", Spfa.dist[T]);
else puts("-1");
}
else puts("-1");
}
int main()
{
// freopen("in.txt", "r", stdin);
while(~scanf("%d%d%d", &n, &m, &T)) solve();
return 0;
}