思路分析讲解
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
#define ll long long
const int N=4010010;
int n,m,ans,cnt;
int e[N],ne[N],w[N],h[2010],idx=1;
int dist[2010],f[2010],k;
int a[2010][2010],ff[2010];
void add(int x,int y,int z){
e[idx]=y,w[idx]=z,ne[idx]=h[x],h[x]=idx++;
}
void spfa(int st)
{
deque<int> que; //用双端队列优化的spfa,不优化也可以。
memset(dist,0x3f,sizeof dist);
for(int i=1;i<=n;i++){ //具有传送门的点,dist设为0,并加入到队列中
if(ff[i]) dist[i]=0,que.push_front(i),f[i]=true;
}
memset(f,0,sizeof f);
dist[st]=0;
if(!f[st]) que.push_front(st);
f[st]=true;
while(que.size())
{
int x=que.front();
que.pop_front();
f[x]=false;
for(int i=h[x];i!=-1;i=ne[i])
{
int tx=e[i];
if(dist[tx]>dist[x]+w[i]){
dist[tx]=dist[x]+w[i];
if(!f[tx]){
if(que.size()&&dist[tx]<=dist[que.front()]){
que.push_front(tx);
}
else que.push_back(tx);
f[tx]=true;
}
}
}
}
}
int main(){
cin>>n>>m>>k;
memset(h,-1,sizeof h);
while(m--){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(!a[x][y]){
add(x,y,z);add(y,x,z);
a[x][y]=idx-2;
a[y][x]=idx-1;
}
else if(a[x][y]&&w[a[x][y]]>z){ //重边处理(其实也可以不用)
w[a[x][y]]=w[a[y][x]]=z;
}
}
for(int i=1;i<=k;i++){
int x;scanf("%d",&x);
ff[x]=true;//将具有传送门的点标记下来
}
for(int i=1;i<n;i++){
spfa(i); //跑n次最短路
ans+=dist[i+1];
}
cout<<ans;
return 0;
}
如果哪里有问题或者不明白的地方欢迎留言评论。
一起学习,共同进步!!