Dijkstra

简溪#

为什么要出现这个算法呢?

因为floyed就是逊啊

floyed的时间复杂度为O(N^3)因为他遍历了每个点到其他点的距离。

而有时只需要一个点到其他点的距离。此时,dijkstra闪亮登场。

该算法的核心是从边入手。
思考一下,如何才能保证一个点能够与另一个点距离确定?

思考片刻……

……

……

……

……

(不是在水😄

……

……

……

……

那就是与起始点相邻的点中,寻找一个距离最近的点。

为什么这个点就是确定的呢?应用floyed的思想:要更新一个点与另一个点的距离,要找一个中继点。详见floyed。​​​​​​如果这个点是最近的,那就无法再找到另一个点,使这个最近点与起始点更近。

举个例子吧
在这里插入图片描述

  • 1 号点的最近点是 4 号点,距离 3 。如果先到 5 号点,更新出来 1 号点到 4 号距离为 10
  • 5 号点的最近点是 3 号点,距离为 2 ,从 1 号点更新 5 号点到 3 号点距离是 11
  • 举个反例,如果把 7 作为 3 号 与 1 号点的距离,那么把 5 号点作为中继点,最短却是 6

最重要的一步已经解决,接下来是通过这个最短边延伸出的点,更新 1 号点与其他点的距离。因此,我们需要一个dis[N]的数组,以记录 1 号点到其他各个点的距离。
还需要一个flag[N]数组,记录dis[i]当中的点那个被选取过(这里的选取指的是在寻找与 1 号点最近点的点),比如 1 号点与 4 号点最近,flag[4]便更新为 1 ,而由 4 号点延伸出的点,不作flag的更新。

接下来的操作已经剧透,就是通过找到的点,遍历与它联通的点,如果 该点到中继点的距离+中继点到起始点的距离,小于dis[N]数组中该点的数组,就更新一下dis[i]。

特别注意

这里的dis[N]数组不一定是 1 号点到其他点的距离,视题目而定。这样的话,flag[N]的初始设定也要改为 flag[beg]=1。
并且题目找的是最短路,也要初始化。(最长路就别了)

代码#

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
int n,m,dis[2510],f[2510][2510],s,t,k;
bool flag[2510];
int main(){
	cin>>n>>m>>s>>t;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(i==j)
				f[i][j]=0;
			else
				f[i][j]=inf; 
		}
	}
	for(int i=1;i<=m;i++){
		int u,v,w;
		cin>>u>>v>>w;
		f[u][v]=min(f[u][v],w);
		f[v][u]=f[u][v];
	}
	for(int i=1;i<=n;i++)
		dis[i]=f[s][i];
	flag[s]=1;
	for(int i=1;i<=n-1;i++){
		int maxn=inf;
		for(int j=1;j<=n;j++){
			if(dis[j]<maxn&&!flag[j]&&dis[j]!=0){
				maxn=dis[j];
				k=j;
			}
		}
		flag[k]=1;
		for(int j=1;j<=n;j++){
			if(dis[j]>dis[k]+f[k][j]){
				dis[j]=dis[k]+f[k][j];
			}
		}
	}
	cout<<dis[t];
	return 0;
}

完结撒花🎉

 

2022年8月24日15:40:52

来放个链式前向星优化的

复制代码
#include<iostream>
#include<cstring>
#include<climits>
#include<vector>
using namespace std;

#define inf 2147483647
#define N 100010
#define ll long long

vector<int> v[N];
int n, s, m, dis[N], k, head[N], tot;
int pos;
bool flag[N];

struct
{
    int to, nxt, val;
}e[N * 5];

void add(int u, int v, int w)
{
    e[++ tot].to = v;
    e[tot].nxt = head[u];
    e[tot].val = w;
    head[u] = tot;
}

int main(){
    cin >> n >> m >> s;
    for(int i = 1; i <= m; ++ i){
        int u, v, w;
        cin >> u >> v >> w;
        add(u, v, w);
    }
    for(int i = 1; i <= n; ++ i)
        dis[i] = inf;
    dis[s] = 0;
    flag[s] = 0;
    pos = s;
    while(flag[pos] == 0)
    {
        ll minn = inf;
        flag[pos] = 1;
        for(int i = head[pos]; i; i = e[i].nxt)
        {
            int t = e[i].to;
            if(!flag[t] && dis[t] > dis[pos] + e[i].val)
                dis[t] = dis[pos] + e[i].val;
        }
        for(int i = 1; i <= n; i ++)
        {
            if(!flag[i] && dis[i] < minn)
            {
                minn = dis[i];
                pos = i;
            }
        }
    }
    for(int i = 1; i <= n; i ++)
        cout << dis[i] << " ";
    
    return 0;
}
复制代码

 

 
posted @   huaziqi  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示