普通矩阵
#include<bits/stdc++.h>
using namespace std;
#define LOCAL
const int inf=0x3f3f3f3f;
const int maxn=1e3+5;
int n,m,vis[maxn],dir[maxn],g[maxn][maxn];
int main(){
#ifdef LOCAL
freopen(".\\in.txt","r",stdin);
freopen(".\\out.txt","w",stdout);
#endif
int s,t,p,q,x;
while(~scanf("%d%d%d",&n,&m,&t)){
for(int i=0;i<=n;i++){
vis[i]=1;dir[i]=inf;
for(int j=0;j<=n;j++){
g[i][j]=inf;
}
}
for(int i=0;i<m;i++){
scanf("%d%d%d",&p,&q,&x);
g[p][q]=min(x,g[p][q]);
}
scanf("%d",&x);
while(x--){
scanf("%d",&s);
g[0][s]=0;
}
s=0;
vis[s]=0;dir[s]=0;
while(s!=t){
int minn=inf,nex;
//加了个辅助起点0 所以0也要算在内。若再加一个辅助终点n+1,则 n+1也要算
for(int i=0;i<=n;i++){
if(g[s][i]!=inf){
dir[i]=min(dir[i],dir[s]+g[s][i]);
}
//只要有路就可以更新最短路径。vis只是用来判断要不要更新最近点的,所以while外面的vis[s]置0
if(dir[i]<minn&&vis[i]){
minn=dir[i];
nex=i;
}
}
if(minn==inf) break;
s=nex;
vis[s]=0;
}
if(s!=t) puts("-1");
else cout<<dir[t]<<endl;
}
}
优先队列+链式前向星
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1005;
const int maxm=21050;
int n,m,s,et,vis[maxn],dis[maxn],cnt;
int head[maxn],e[maxm],c[maxm],nex[maxm];
void creat(int u,int v,int w){
e[++cnt]=v;
c[cnt]=w;
nex[cnt]=head[u];
head[u]=cnt;
}
struct node{
int id,w;
friend bool operator< (node a,node b){
return a.w>b.w;
}
};
priority_queue<node>q;
void dij(){
s=0;dis[s]=0;
q.push({0,0});
while(!q.empty()){//可能一直走不到e,所以不能直接用!vis[e]
node cur=q.top();q.pop();
int u=cur.id;
if(!vis[u]){
vis[u]=1;
for(int i=head[u];i;i=nex[i]){
int v=e[i],w=c[i];
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
q.push({v,dis[v]});
}
}
}
}
}
int main(){
int p,q,t,w;
while(~scanf("%d%d%d",&n,&m,&et)){
for(int i=0;i<=n;i++){
vis[i]=0;dis[i]=inf;head[i]=0;
}
cnt=0;//多组数据建边前cnt清0
for(int i=0;i<m;i++){
scanf("%d%d%d",&p,&q,&t);
creat(p,q,t);
//多条边取最小,链式前向星得用优先队列
}
cin>>w;
for(int i=1;i<=w;i++){
scanf("%d",&s);
creat(0,s,0);
}
// vis[s]=1;这句不能有 ,优先队列法写最短路vis[s]在不改!!!!
dij();
if(dis[et]==inf) cout<<"-1"<<endl;
else cout<<dis[et]<<endl;
}
}