题目链接:Fire-Fighting Hero
大意:给出多个点,问这些点,到所有点的最短路当中的最大值是多少。和一个单独的点到所有点的最短路的最大值除C之后比较,输出最小的最大值。
我们肯定不能以每一个点去跑最短路,我们分析可知,因为从每个点出发是一样的,所以我们可以单独建立一个点,指向这些点,路程为0,最后跑这个点到所有点的最短路。单独的点就直接跑最短路即可。
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1010,M=1000010;
int T,n,m,s,k,c,st,d[N],vis[N];
int head[N],nex[M],to[M],w[M],tot;
inline void add(int a,int b,int c){
to[++tot]=b; w[tot]=c; nex[tot]=head[a]; head[a]=tot;
}
int dijkstra(int x){
memset(d,0x3f,sizeof d); d[x]=0; memset(vis,0,sizeof vis);
priority_queue<pair<int,int> > q; q.push({0,x});
while(q.size()){
int u=q.top().second; q.pop();
if(vis[u]) continue; vis[u]=1;
for(int i=head[u];i;i=nex[i]){
if(d[to[i]]>d[u]+w[i]){
d[to[i]]=d[u]+w[i]; q.push({-d[to[i]],to[i]});
}
}
} int mx=0;
for(int i=1;i<=n;i++) if(d[i]!=0x3f3f3f3f3f3f3f3f)mx=max(mx,d[i]);
return mx;
}
signed main(){
scanf("%lld",&T);
while(T--){
tot=0; memset(head,0,sizeof head);
scanf("%lld %lld %lld %lld %lld",&n,&m,&s,&k,&c); st=n+1;
for(int i=1;i<=k;i++){
int x; scanf("%lld",&x); add(st,x,0);
}
while(m--){
int a,b,c; scanf("%lld %lld %lld",&a,&b,&c);
add(a,b,c); add(b,a,c);
}
int res1=dijkstra(st); int res2=dijkstra(s);
if(res2<=res1*c) printf("%lld\n",res2);
else printf("%lld\n",res1);
}
return 0;
}