# Dijkstra算法简介

Dijkstra算法主要用来解决边权为正时的单源最短路问题(就是从一个源点出发，到所有结点的最短路)，同时适用于有向图和无向图

# Dijkstra算法模板

const int INF=1<<30;
int v[maxn];
int d[maxn];
int w[maxn][maxn];

memset(v,0,sizeof(v));
for(int i=0;i<n;i++) d[i]=(i==0?0:INF);
for(int i=0;i<n;i++) {
int x,m=INF;
for(int y=0;y<n;y++) if(!v[y]&&d[y]<=m) m=d[x=y];
v[x]=1;
for(int y=0;y<n;y++) d[y]=min(d[y],d[x]+w[x][y]);
}


struct edge{   //储存边
int from,to,w;
edge(int u,int v,int d):from(u),to(v),w(d){}
}
struct node{		//用来结合优先队列使用
int d,u;
bool operator < (const node &rhs) const {
return d>rhs.d;
}
}
vector<edge>edges;
vector<int>g[maxn];
int d[maxn];

edges.push_back(edge(from,to,wei));
m=edges.size();
g[from].push_back(m-1);
}

void dij(){
priority_queue<node> q;
for(int i=0;i<=t;i++) d[i]=INF;
d[s]=0;
memset(done,0,sizeof(done));
q.push((node){0,s});
while(!q.empty()){
node x=q.top();q.pop();
int u=x.u;
if(done[u]) continue;
done[u]=1;
if(d[to[i]]>d[u]+dis[i]){  	//松弛操作
d[to[i]]=d[u]+dis[i];
q.push((node){d[to[i]],dis[i]});
}
}
}
}


# 递归打印最短路径

void print(int t){  //s为源点，t为终点
printf("%d  ",t);
if(s==t) return;
for(int i=0;i<n;i++){
if(d[t]==d[t]+w[i][j]){
print(i);
break;
}
}
}


## dij算法解决多源多汇问题

AC代码

#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int maxn=100005;
const long long INF=0x3f3f3f3f3f3f3f3f;
int tot,k;
long long d[maxn];
struct edge{
int to,next;
long long dis;
}edges[maxn];
struct node{
int u;
long long d;
bool operator < (const node& rhs) const{
return d>rhs.d;
}
};
priority_queue<node>q;
void addedge(int from,int to,long long w){
edges[tot].to=to;
edges[tot].dis=w;
}

long long dij(){
while(!q.empty()){
struct node x=q.top();q.pop();
if(mark[x.u]) return x.d;
if(done[x.u]) continue;
done[x.u]=1;
if(d[edges[i].to]>d[x.u]+edges[i].dis){
d[edges[i].to]=d[x.u]+edges[i].dis;
q.push(node{edges[i].to,d[edges[i].to]});
}
}
}
return INF;
}

void init(){
memset(done,0,sizeof(done));
memset(mark,0,sizeof(mark));
memset(d,0x3f3f3f3f3f3f3f3f,sizeof(d));
while(!q.empty()) q.pop();
}

int main(){
int t,n,m,kase=0;
int u,v;
long long w;
scanf("%d",&t);
while(t--){
tot=0;
long long ans=INF;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
scanf("%d%d%lld",&u,&v,&w);
}
scanf("%d",&k);
for(int i=0;i<k;i++) scanf("%d",a+i);
for(int i=0;i<20;i++){
init();
for(int j=0;j<k;j++){
if(a[j]&(1<<i)){
mark[a[j]]=1;
}
else q.push(node{a[j],d[a[j]]=0});
}
ans=min(ans,dij());
}
printf("Case #%d: %lld\n",++kase,ans);
}
}


## https://cn.vjudge.net/problem/766699/origin

ac代码

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<map>
using namespace std;
int t,n,k,m,s;
double X;
const int maxn=1e6;
int done[maxn];
double d[maxn];
struct edge{
int from,to;
double dis;
edge(int u,int v,double d):from(u),to(v),dis(d){}
};
vector<edge>es;
vector<int>g[maxn];
struct node{
double d;
int u;
bool operator <(const struct node & rhs) const{
return d > rhs.d;
}
};

es.push_back(edge(u,v,d));
es.push_back(edge(v,u,d));
int m=es.size();
g[u].push_back(m-2);
g[v].push_back(m-1);
}

void dij(int s){
priority_queue<node>q;
for(int i=0;i<=n;i++) d[i]=0x3f3f3f3f3f3f3f3f;
d[s]=0;
memset(done,0,sizeof(done));
q.push((node){0,s});
while(!q.empty()){
node x=q.top();q.pop();
int u=x.u;
if(done[u]) continue;
done[u]=1;
for(int i=0;i<g[u].size();i++){
edge& e=es[g[u][i]];
if(d[e.to]>d[u]+e.dis){
d[e.to]=d[u]+e.dis;
q.push((node){d[e.to],e.to});
}
}
}
}

int main(){
scanf("%d",&t);
while(t--){
int a,b;
double w;
scanf("%d%d%lf%d%d",&n,&k,&X,&m,&s);
for(int i=0;i<=n;i++) g[i].clear();es.clear();
for(int i=0;i<m;i++){
scanf("%d%d%lf",&a,&b,&w);
}
dij(s);
for(int i=1;i<=n;i++){
if(i!=n) printf("%lld ",(long long)d[i]);
else printf("%lld\n",(long long)d[i]);
}
}
return 0;
}


03-08 44万+
03-30 10万+

01-24 1万+
03-25 4024
12-28 7万+
01-08 1446
07-13 3260