最短路——Dijkstra
文章目录
Dijkstra
算法描述
- 设置出发顶点为v,顶点集合V{v1,v2,vi…vn},v到V中各顶点的距离构成距离集合dis,dis{d1,d2,di…dn},Dis集合记录着v到图中各顶点的距离(到自身可以看作0,v到vi距离对应为di,初始时,设置di=oo)
- 从dis中选择值最小的di并移出dis集合,同时移出V集合中对应的顶点vi,此时的v到vi即为最短路径
- 更新dis集合,更新规则为:比较v到V集合中顶点的距离值,与v通过vi到V集合中顶点的距离值,保留值较小的一个
- 重复执行2、3步骤,直到编历完所有的点
模板
1.基于邻接表的Dijkstra
void Dijkstra(int s){
memset(dist,INF,sizeof(dist));
memset(vis,0,sizeof(vis));
dist[s]=0;
for(int k=0;k<n;k++){
int u,mind=INF;
for(int i=1;i<=n;i++){
if(dist[i]<mind && !vis[i]){
mind=dist[i];
u=i;
}
}
vis[u]=1;
for(int i=head[u];i;i=edge[i].next_edge){
int v=edge[i].to,w=edge[i].w;
if(dist[v]>dist[u]+w){
dist[v]=dist[u]+w;
}
}
}
}
2.优先队列优化的Dijkstra
struct node{
int id,dis;
node(){}
node(int idd,int diss):id(idd),dis(diss){}
bool operator <(const node &a) const{
return a.dis<dis;
}
};
void Dijkstra(){
memset(dist,INF,sizeof(dist));
memset(vis,0,sizeof(vis));
dist[1]=0;
priority_queue<node> q;
q.push(node(1,dist[1]));
while(!q.empty()){
node t=q.top();
q.pop();
int u=t.id;
if(vis[u]) continue;
for(int i=head[u];i;i=edge[i].next_edge){
int v=edge[i].to,w=edge[i].w;
if(dist[v]>dist[u]+w){
dist[v]=dist[u]+w;
q.push(node(v,dist[v]));
}
}
}
}
例题
POJ-2387
POJ2387 Til the Cows Come Home
题目描述
具体代码
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1002,maxe=4002;
int n,m,num_edge;
int dist[maxn],head[maxn];
bool vis[maxn];
struct E{
int to,next_edge,w;
}edge[maxe];
void add_edge(int u,int v,int w){
edge[++num_edge].w=w;
edge[num_edge].to=v;
edge[num_edge].next_edge=head[u];
head[u]=num_edge;
}
void Dijkstra(int s){
memset(dist,INF,sizeof(dist));
memset(vis,0,sizeof(vis));
dist[s]=0;
for(int k=0;k<n;k++){
int u,mind=INF;
for(int i=1;i<=n;i++){
if(dist[i]<mind && !vis[i]){
mind=dist[i];
u=i;
}
}
vis[u]=1;
for(int i=head[u];i;i=edge[i].next_edge){
int v=edge[i].to,w=edge[i].w;
if(dist[v]>dist[u]+w){
dist[v]=dist[u]+w;
}
}
}
}
int main(){
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add_edge(x,y,z);
add_edge(y,x,z);
}
Dijkstra(1);
printf("%d\n",dist[n]);
return 0;
}
POJ-3159
[POJ-3159 Candies ]https://vjudge.csgrandeur.cn/problem/POJ-3159)
题目描述
具体代码
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=3e4+2;
const int M=150002;
int n,m,num_edge;
int head[maxn],dist[maxn];
bool vis[maxn];
struct Edge{
int to,w,next_edge;
}edge[M];
struct node{
int id,dis;
node(){}
node(int idd,int diss):id(idd),dis(diss){}
bool operator <(const node &a) const{
return a.dis<dis;
}
};
void add_edge(int u,int v,int w){
edge[++num_edge].to=v;
edge[num_edge].w=w;
edge[num_edge].next_edge=head[u];
head[u]=num_edge;
}
void Dijkstra(){
memset(dist,INF,sizeof(dist));
memset(vis,0,sizeof(vis));
dist[1]=0;
priority_queue<node> q;
q.push(node(1,dist[1]));
while(!q.empty()){
node t=q.top();
q.pop();
int u=t.id;
if(vis[u]) continue;
for(int i=head[u];i;i=edge[i].next_edge){
int v=edge[i].to,w=edge[i].w;
if(dist[v]>dist[u]+w){
dist[v]=dist[u]+w;
q.push(node(v,dist[v]));
}
}
}
}
int main(){
while(~scanf("%d%d",&n,&m)){
num_edge=0;
memset(head,0,sizeof(head));
for(int i=1;i<=m;i++){
edge[i].next_edge=0;
}
for(int i=0;i<m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
}
Dijkstra();
printf("%d\n",dist[n]);
}
return 0;
}
set(head,0,sizeof(head));
for(int i=1;i<=m;i++){
edge[i].next_edge=0;
}
for(int i=0;i<m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
}
Dijkstra();
printf("%d\n",dist[n]);
}
return 0;
}