正着作一遍\(dij\)求出最短路徑以及從誰轉移過來的,反過來作一遍,若是兩個點不禁同一個點轉移過來就更新答案。ios
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; #define ll long long #define MAX 100100 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } struct Line{int v,next,w;}e[MAX*10]; int h[MAX],cnt=1; inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;} int col[MAX];ll dis1[MAX],dis2[MAX];bool vis[MAX]; struct Node{int x,fr;ll dis;}; bool operator<(Node a,Node b){return a.dis>b.dis;} priority_queue<Node>Q; int n,m,K,a[MAX];ll ans; void Dijkstra1() { memset(dis1,63,sizeof(dis1));memset(vis,0,sizeof(vis)); for(int i=1;i<=K;++i)dis1[a[i]]=0,col[a[i]]=a[i],Q.push((Node){a[i],a[i],0}); while(!Q.empty()) { Node p=Q.top();Q.pop();int u=p.x; if(vis[u])continue;vis[u]=true; for(int i=h[u];i;i=e[i].next) { int v=e[i].v;if(!(i&1))continue; if(dis1[v]>dis1[u]+e[i].w) col[v]=col[u],dis1[v]=dis1[u]+e[i].w,Q.push((Node){v,col[u],dis1[v]}); } } } void Dijkstra2() { memset(dis2,63,sizeof(dis2));memset(vis,0,sizeof(vis)); for(int i=1;i<=K;++i)dis2[a[i]]=0,Q.push((Node){a[i],a[i],0}); while(!Q.empty()) { Node p=Q.top();Q.pop();int u=p.x; if(vis[u])continue;vis[u]=true; for(int i=h[u];i;i=e[i].next) { int v=e[i].v;if(i&1)continue; if(col[v]!=col[u])ans=min(ans,dis2[u]+e[i].w+dis1[v]); if(dis2[v]>dis2[u]+e[i].w) dis2[v]=dis2[u]+e[i].w,Q.push((Node){v,col[u],dis2[v]}); } } } int main() { int T=read(); while(T--) { n=read();m=read();K=read(); for(int i=1,u,v,w;i<=m;++i) u=read(),v=read(),w=read(),Add(u,v,w),Add(v,u,w); for(int i=1;i<=K;++i)a[i]=read(); ans=1e18;Dijkstra1();Dijkstra2(); printf("%lld\n",ans); for(int i=1;i<=n;++i)h[i]=col[i]=0;cnt=1; } return 0; }