Dijkstra算法(例题)

Dijkstra算法
从起点到终点求最短路 — 使用要求权值为正

1、求短路I
https://www.acwing.com/problem/content/851/

//题目 点数 500  边数  1e5 

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 510,M = 1e5+10;
//时间复杂度O(n^m) 
int n,m;
//邻接矩阵
int a[N][N];

bool vis[N];//记录已经遍历的点

//记录起点到某点的最短路径
int d[N];

int dijkstra(){
    
    
    d[1]=0;

    for(int i=1;i<=n;++i){
    
    
        int t = -1;
        for(int j=1;j<=n;++j){
    
    
            if(!vis[j]&&(d[t]>d[j]||t==-1)){
    
    
                //找没有遍历的点 && 对于起点来说最短的点
                t=j;
            }
        }
        vis[t]=true;
        
        for(int j=1;j<=n;++j){
    
    
            //更新d中值
            //更新起点到j点最短距离
            
            d[j] = min(d[j],d[t]+a[t][j]);
        }
    }
    
    if(d[n]>=0x3f3f3f3f) return -1;
    return d[n];
}
int main(){
    
    
    memset(a,0x3f,sizeof a);
    memset(d,0x3f,sizeof d);
    cin>>n>>m;
    int x,y,z;
    for(int i=0;i<m;++i){
    
    
        cin>>x>>y>>z;
        //可能出现重边,取最短的那条   
        a[x][y]=min(a[x][y],z);
    }
    cout<<dijkstra();
    return 0;
}

2、求最短路II
https://www.acwing.com/problem/content/852/

数据范围 1e5 时间复杂度O(n^2) 超时!

优化思路:
1、循环每个点
2、每次找距离起点最短距离的点
3、进行更新

采用优先队列 优化2
采用邻接表 优化3
优化后时间复杂度 O(mlogn)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N =1e6;

int n,m;

int d[N];
bool vis[N];
typedef pair<int,int>PII;
//构建邻接表
int e[N],ne[N],w[N],h[N],idx;

void add(int a,int b,int c){
    
    
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}

int dijkstra(){
    
    
    d[1]=0;
    
    //根据距离来排--从小到大
    priority_queue<PII,vector<PII>,greater<PII>>q;
    //pair 根据first来排序
    q.push({
    
    0,1});//距离  结点
    
    while(q.size()){
    
    
        
        auto t = q.top();
        q.pop();
        //类似上面的 t 
        int k = t.second,distance=t.first;
        
        //需要判断---不然超时
        if(vis[k]) continue;
        vis[k] = true;
        
        //进行更新
        for(int i=h[k];i!=-1;i=ne[i]){
    
    
            
            int j = e[i];
  				
            //如果遍历过,跳过
            if(vis[j]) continue;
            //w[i]存储的是此时结点j的权值
            //进行更新
            if(d[j]>d[k]+w[i]){
    
    
                d[j]=d[k]+w[i];
                q.push({
    
    d[j],j});
            }
            
        }
    }
    if(d[n]>=0x3f3f3f3f) return -1;
    return d[n];
}

int main(){
    
    
    memset(h,-1,sizeof h);
    memset(d,0x3f,sizeof d);
    int x,y,z;
    cin>>n>>m;
    for(int i=0;i<m;++i) {
    
    
        cin>>x>>y>>z;
        add(x,y,z);      
    }
    cout<<dijkstra();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44922497/article/details/114229219