圖論:Dijkstra算法

昨天介紹了最小生成樹的兩個算法,最小生成樹的兩個算法旨在求解無向有權圖中的最小代價聯通圖的問題,那么對于有向有權圖,從起點到終點的最小花費代價問題就可以用 Dijkstra 算法來解決而且Dijkstra算法可以求出來從起始點開始到所有節點的最短距離!他和最小生成樹的prim算法十分類似,也是三部曲,最短路是圖論中的經典問題即:給出一個有向圖,一個起點,一個終點,問起點到終點的最短路徑。

樸素版Dijkstra算法

dijkstra算法:在有權圖(權值非負數)中求從起點到其他節點的最短路徑算法。

  • dijkstra 算法可以同時求起點到所有節點的最短路徑
  • 權值不能為負數

dijkstra三部曲

  1. 第一步,選源點到哪個節點近且該節點未被訪問過
  2. 第二步,該最近節點被標記訪問過
  3. 第三步,更新非訪問節點到源點的距離(即更新ans數組)

ans數組用來記錄每一個節點距離起始點的最小距離。

循環n次,每一次都能確定一個最優點(其實和prim算法一樣都是用了貪心的策略,因為之后的所有的點的選取都是基于目前所有的可達路徑,所以要在當前所有的可達路徑中選一個權值最小的路徑,以其為基準再繼續更新之后的可達點,當一個點被更新到最短路中的時候【即被標記訪已訪問的時候】,就說明在他之前所有可以到達他的路徑都遍歷過了,因為他是被所有的前面的可達他的點都遍歷過的)。

說多了容易迷糊,來看一個模版題來促進對算法以及代碼模板的理解

參加科學大會

題目鏈接:參加科學大會

這道題還是相對簡單一點的,因為已經固定了起點是1,終點是n,所以不需要對起點和終點進行分析,直接套用模板即可。注意建圖的時候如果用鄰接矩陣時開[n][n]二維數組m只是邊數!

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int inf = 0x3f3f3f3f3f3f3f3f;
int n,m;void solve()
{cin>>n>>m;vector<vector<int>> e(n+1,vector<int>(n+1,inf));//建圖vector<bool> v(n+1,false);//標記數組vector<int> ans(n+1,inf);//所有的點到起點的最短距離(最小代價)for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;e[u][v] = w;//建圖}ans[1] = 0;//Dijkstra算法三部曲for(int i=1;i<=n;i++){int mi = inf;int index = 0;//遍歷找不在未訪問的距離起點最近的點for(int j=1;j<=n;j++)//因為之后的所有答案都會在現在的路徑基礎上累加 所以在現有路徑中挑最短的{if(!v[j] && ans[j] < mi){mi = ans[j];index = j;}}//將最近點標記為已訪問v[index] = true;//更新所有未訪問的可達點到起點的最短距離for(int j=1;j<=n;j++){if(!v[j] && e[index][j] + ans[index] < ans[j]) ans[j] = ans[index] + e[index][j];}}if(ans[n] == inf) cout<<"-1"<<endl;else cout<<ans[n]<<endl;
}signed main()// Don't forget pre_handle!
{IOSint T=1;
//	cin>>T;while(T--) solve(); return 0;
} 

這里奉上Dijkstra樸素版的模板,ICPCer可拿~【適用于n<=1e3且沒有負邊權(用SPFA)】?

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pii pair<int,int>
#define fi first
#define se second
const int inf = 0x3f3f3f3f3f3f3f3f;  // 定義無窮大void solve()
{// 輸入點數和邊數int n,m;cin>>n>>m;// 鄰接矩陣存圖,初始化為infvector<vector<int>> e(n+1,vector<int>(n+1,inf));// 標記數組,記錄是否已確定最短路vector<bool> v(n+1,false);// 存儲起點到各點的最短距離vector<int> ans(n+1,inf);// 建圖,處理邊輸入for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;e[u][v]=w;  // 有向圖建邊// e[v][u]=w; // 如果是無向圖需要加上這行}// 初始化,起點距離設為0ans[1]=0;//起點和終點看題目要求// Dijkstra主過程,循環n次for(int i=1;i<=n;i++){int mi=inf;     // 當前未處理節點中的最小距離int index=0;    // 對應的節點編號// 遍歷所有節點,找出未處理且距離最小的節點for(int j=1;j<=n;j++){if(!v[j]&&ans[j]<mi){mi=ans[j];index=j;}}// 標記該節點已處理v[index]=true;// 松弛操作:通過該節點更新其他節點的距離for(int j=1;j<=n;j++){if(!v[j]&&e[index][j]+ans[index]<ans[j]){ans[j]=ans[index]+e[index][j];}}}// 輸出結果,如果不可達輸出-1if(ans[n]==inf) cout<<"-1"<<endl;else cout<<ans[n]<<endl;
}
signed main()
{IOS;int T=1;//cin>>T;while(T--){solve();}return 0;
}

堆優化版Dijkstra

題目重現

堆優化就是利用小頂堆來避免每次都遍歷尋找最值,并且用鄰接表代替鄰接矩陣更能優化第二個for循環,因為鄰接表中存的就是這個點之后所連接的點,直接用auto遍歷即可,不過需要分清里面的fi和se分別都對應的哪些變量!

參加科學大會:堆優化版代碼:

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int inf = 0x3f3f3f3f;
const int N = 520;
vector<vector<pii>> e(N);//鄰接表
vector<int> ans(N,inf);//各個點到起點的最近距離
vector<bool> f(N,false);//標記訪問數組
priority_queue<pii,vector<pii>,greater<pii>> q;//最小堆優化
int n,m;void solve()
{cin>>n>>m;for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;e[u].push_back({v,w});//用鄰接表建圖}ans[1] = 0;q.push({ans[1],1});//fi為ans se為索引while(!q.empty()){int mi = q.top().fi;int index = q.top().se;q.pop();if(f[index]) continue;//如果訪問過就continue!!!!!f[index] = true;for(auto i : e[index]){//i.fi是點的索引 i.se是邊權if(ans[index] + i.se < ans[i.fi]){ans[i.fi] = ans[index] + i.se;q.push({ans[i.fi],i.fi});//別忘記在找到一個點之后就更新ans[i.fi]//在找到更優解的時候再加入隊列!!!}}}if(ans[n] == inf) cout<<"-1"<<endl;else cout<<ans[n]<<endl;
}signed main()// Don't forget pre_handle!
{IOSint T=1;
//	cin>>T;while(T--) solve(); return 0;
} 

這里同樣奉上堆優化版的模板,ICPCer可拿~

#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int inf = 0x3f3f3f3f;
const int N = 520;// Dijkstra堆優化模板(鄰接表實現)
// 適用情況:稀疏圖,點數較多(mlogn復雜度)
// 功能:求單源最短路,解決非負權圖
// 注意:inf需要根據題目調整,避免溢出vector<vector<pii>> e(N);  // 鄰接表存圖
vector<int> ans(N, inf);   // 存儲起點到各點的最短距離
vector<bool> f(N, false);  // 標記是否已確定最短路
priority_queue<pii, vector<pii>, greater<pii>> q;  // 小根堆優化
int n, m;void solve()
{cin >> n >> m;// 鄰接表建圖for(int i = 1; i <= m; i++){int u, v, w;cin >> u >> v >> w;e[u].push_back({v, w});  // 有向圖建邊// e[v].push_back({u, w}); // 無向圖需要加上這行}// 初始化起點距離ans[1] = 0;q.push({ans[1], 1});  // first存距離,second存節點編號// Dijkstra主過程while(!q.empty()){int mi = q.top().fi;    // 當前最小距離int index = q.top().se; // 對應節點q.pop();// 如果該節點已確定最短距離,跳過if(f[index]) continue;f[index] = true;  // 標記已確定// 遍歷所有鄰接點for(auto i : e[index]){// i.fi是鄰接點索引,i.se是邊權if(ans[index] + i.se < ans[i.fi]){ans[i.fi] = ans[index] + i.se;  // 松弛操作q.push({ans[i.fi], i.fi});      // 將新距離加入堆}}}// 輸出結果if(ans[n] == inf) cout << "-1" << endl;else cout << ans[n] << endl;
}signed main()
{IOS;int T = 1;//cin >> T;while(T--){solve();}return 0;
}

一定一定要注意訪問過就continue!每次的操作(步驟1和3都是對未訪問元素的操作!)

接下來就運用一下Dijkstra算法吧!

代價轉移

題目鏈接:代價轉移

這道題與眾不同的就是沒有直接給出圖的構造,而是需要不斷的動態的更新,不過換湯不換藥,不過要注意對于動態生成的節點要判斷是否合理,如果不合理的話就應該continue防止導致未定義越界(負節點 或 超大節點)導致死循環!max(a,b) * 2僅僅是合理的范圍,不是動態生成的點的范圍

下面來看詳細代碼:

// Problem: 代價轉移
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/113664/B
// Memory Limit: 512 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
#define int long long 
#define endl '\n'
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define pii pair<int,int>
#define fi first
#define se second
const int inf = 0x3f3f3f3f3f3f3f3f;void solve()
{int a,b,c1,c2,c3;cin>>a>>b>>c1>>c2>>c3;if(a >= b)//對特殊情況進行判斷{cout<<(a - b) * c2 <<endl;return ;}//Dijkstra求最短路:int N = max(a,b) * 2;//先預定一個可達點范圍vector<int> ans(N+1,inf);//初始化為最大vector<bool> v(N+1,false);//標記訪問數組priority_queue<pii,vector<pii>,greater<pii>> q;//小頂堆ans[a] = 0;//依舊初始化q.push({0,a});//首先將起點入隊while(!q.empty()){int value = q.top().fi;//直接找出最小值int index = q.top().se;//q.fi是代價 q.se數q.pop();//將這個點放入最短路徑中了(不在非訪問的數里面了)if(v[index]) continue;//一定一定別忘記 Dijkstra的核心v[index] = true;//標記已訪問pii adj[] = {{index + 1,c1},{index - 1,c2},{index * 2,c3}};//動態生成三個新節點for(auto i : adj)//對三個節點進行遍歷{if(i.fi < 1 || i.fi > N) continue;//注意要對新節點的合理性檢查 常規圖中都是合理點 但是這里是不斷動態生成的點 需要檢查if(ans[index] + i.se < ans[i.fi])//更新更優解{ans[i.fi] = ans[index] + i.se;q.push({ans[i.fi],i.fi});//在找到滿足條件的值之后再入隊}}}cout<<ans[b]<<endl;
}signed main()// Don't forget pre_handle!
{IOSint T=1;cin>>T;while(T--) solve(); return 0;
} 

以上內容就是關于Dijkstra算法的兩種實現思路了,感興趣的小伙伴可以收藏起來到整理模版的時候直接食用!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/90762.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/90762.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/90762.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

WPFC#超市管理系統(2)顧客管理、供應商管理、用戶管理

超市管理系統3. 顧客管理3.1 顧客新增3.2 DataGrid樣式3.3 顧客刪除3.4 顧客修改4. 供應商管理4.1 供應商管理主界面4.2 新增供應商4.3 修改供應商5. 用戶管理5.1 用戶管理主界面5.2 新增用戶5.3 修改用戶總結3. 顧客管理 在CustomerView.xaml使用命令綁定方式添加頁面加載Loa…

Windows本地部署DeepSeek

1、Ollama1、下載Ollama安裝包https://ollama.com/download&#xff08;如果下載很慢 可以直接找我拿安裝包&#xff09;2、使用命令行安裝打開cmd 將下載的安裝包OllamaSetup.exe 放到想要安裝的目錄下。&#xff08;如果直接雙擊&#xff0c;會裝到C盤&#xff09;例如想裝到…

基于Python的新聞爬蟲:實時追蹤行業動態

引言 在信息時代&#xff0c;行業動態瞬息萬變。金融從業者需要實時了解政策變化&#xff0c;科技公司需要跟蹤技術趨勢&#xff0c;市場營銷人員需要掌握競品動向。傳統的人工信息收集方式效率低下&#xff0c;難以滿足實時性需求。Python爬蟲技術為解決這一問題提供了高效方…

阿里視頻直播解決方案VS(MediaMTX + WebRTC) 流媒體解決方案

背景&#xff1a; 公司采購了新的攝像頭&#xff0c;通過rtsp或者rtmp推流到云平臺&#xff0c;云平臺內部進行轉碼處理&#xff0c;客戶端使用HLS或HTTP-FLV播放&#xff0c;移動App可能使用HLS或私有SDK&#xff0c;超低延時則采用WebRTC。 技術選型&#xff1a; RTSP&…

day33:零基礎學嵌入式之網絡——TCP并發服務器

一、服務器1.服務器分類單循環服務器&#xff1a;只能處理一個客戶端任務的服務器并發服務器&#xff1a;可同時處理多個客戶端任務的服務器二、TCP并發服務器的構建1.如何構建&#xff1f;&#xff08;1&#xff09;多進程&#xff08;每一次創建都非常耗時耗空間&#xff0c;…

VR全景制作的流程?VR全景制作可以用在哪些領域?

VR全景制作的流程&#xff1f;VR全景制作可以用在哪些領域&#xff1f;VR全景制作&#xff1a;流程、應用與未來虛擬現實&#xff08;VR&#xff09;全景制作正迅速改變我們的感官體驗&#xff0c;使我們能夠身臨其境地探索虛擬世界&#xff0c;享受沉浸式的奇妙感受。那么&…

用LangChain重構客服系統:騰訊云向量數據庫+GPT-4o實戰

人們眼中的天才之所以卓越非凡&#xff0c;并非天資超人一等而是付出了持續不斷的努力。1萬小時的錘煉是任何人從平凡變成超凡的必要條件。———— 馬爾科姆格拉德威爾 目錄 一、傳統客服系統痛點與重構價值 1.1 傳統方案瓶頸分析 1.2 新方案技術突破點 二、系統架構設計&…

主要分布在腹側海馬體(vHPC)CA1區域(vCA1)的混合調諧細胞(mixed-tuning cells)對NLP中的深層語義分析的積極影響和啟示

腹側海馬體CA1區&#xff08;vCA1&#xff09;的混合調諧細胞&#xff08;mixed-tuning cells&#xff09;通過整合情感、社會關系、空間概念等多模態信息&#xff0c;形成動態的情景化語義表征&#xff0c;為自然語言處理&#xff08;NLP&#xff09;的深層語義分析提供了重要…

ESP32的ADF詳解:6. Audio Processing的API

一、Downmix 1. 核心功能 將基礎音頻流和新加入音頻流混合為單一輸出流&#xff0c;支持動態增益控制和狀態轉換。輸出聲道數與基礎音頻一致&#xff0c;新加入音頻自動轉換聲道匹配。2. 關鍵特性聲道處理 輸出聲道數 基礎音頻聲道數新加入音頻自動轉換聲道&#xff08;如立體…

Qt(基本組件和基本窗口類)

一、基本組件1. Designer設計師為什么要上來先將這個東西呢&#xff0c;這個是QT外置的設計界面的工具&#xff0c;沒啥用&#xff0c;所以了解一下。我們用的多的是QT內置的界面設計&#xff0c;只需要我們雙擊我們創建的項目的.ui文件就可以進入這個界面&#xff0c;你對界面…

docker與k8s的容器數據卷

Docker容器數據卷 特性 docker鏡像由多個只讀層疊加而成&#xff0c;啟動容器時&#xff0c;Docker會加載只讀鏡像層并在鏡像棧頂部添加一個讀寫層。如果運行中的容器修改了現有的一個已經存在的文件&#xff0c;那么該文件將會從讀寫層下面的只讀層復制到讀寫層&#xff0c;該…

自然語言處理技術應用領域深度解析:從理論到實踐的全面探索

1. 引言:自然語言處理的技術革命與應用前景 自然語言處理(Natural Language Processing,NLP)作為人工智能領域的核心分支,正在以前所未有的速度改變著我們的數字化生活。從最初的規則基礎系統到如今基于深度學習的大語言模型,NLP技術經歷了從理論探索到實際應用的深刻變…

OpenGLRender開發記錄(二): 陰影(shadowMap,PCF,PCSS)

目錄已實現功能陰影shadowMapPCFPCSS實現shadowMapPCFPCSS陰影GitHub主頁&#xff1a;https://github.com/sdpyy1 OpenGLRender:https://github.com/sdpyy1/CppLearn/tree/main/OpenGL 已實現功能 除了上次實現IBL之外&#xff0c;項目目前新增了imGUI的渲染&#xff0c;更方便…

Linux:日志亂碼

1、Linux日志亂碼可能是XShell客戶端編碼沒設置為UTF-8引起的&#xff0c;按照以下步驟&#xff0c;設置終端格式&#xff1a;中文版&#xff1a;打開Xshell會話屬性&#xff08;文件→屬性→終端→編碼&#xff09;&#xff0c;選擇與服務器一致的編碼格式&#xff08;如UTF-8…

Rouge:面向摘要自動評估的召回導向型指標——原理、演進與應用全景

“以n-gram重疊量化文本生成質量&#xff0c;為摘要評估提供可計算標尺” Rouge&#xff08;Recall-Oriented Understudy for Gisting Evaluation&#xff09; 是由 南加州大學信息科學研究所&#xff08;ISI&#xff09;的Chin-Yew Lin 于2004年提出的自動文本摘要評估指標&am…

[STM32][HAL]stm32wbxx 超聲波測距模塊實現(HY-SRF05)

前言 在電子技術應用中,距離測量是一個常見且重要的需求。超聲波模塊因其測量精度較高、成本較低、易于使用等優點,被廣泛應用于機器人避障、液位檢測、智能停車系統等領域。該文主要講解以stm32wb芯片為主控,用HAL庫來對HY-SRF05超聲波模塊進行代碼編寫,實現基本的驅動和測…

MySQL 性能調優實戰指南:從診斷到優化全解析

引言在日常的數據庫運維工作中&#xff0c;我們經常需要對 MySQL 數據庫進行診斷和性能分析。本文將介紹一套全面的 MySQL 診斷腳本&#xff0c;適用于 MySQL 8.0&#xff08;兼容 8.0.15 及以上版本&#xff09;&#xff0c;涵蓋事務鎖分析、性能瓶頸定位、配置檢查、連接狀態…

8. 狀態模式

目錄一、應用背景二、狀態模式2.1 解決的問題2.2 角色2.3 實現步驟三、通用設計類圖四、實現4.1 設計類圖4.2 狀態轉換圖4.3 代碼實現一、應用背景 某對象發生變化時&#xff0c;其所能做的操作也隨之變化。應用程序的可維護性和重用性差代碼的邏輯較復雜 二、狀態模式 2.1 …

php語法--foreach和in_array的使用

文章目錄foreach基礎語法&#xff1a;案例1&#xff1a;引用傳遞模式&#xff1a;嵌套數組處理&#xff1a;避免在循環中計算數組長度&#xff1a;使用引用減少內存拷貝&#xff1a;打印數組in_array基礎使用嚴格使用foreach 基礎語法&#xff1a; foreach ($iterable as $va…

ES6模塊詳解:核心語法與最佳實踐

以下是 EMAScript 6&#xff08;ES6&#xff09;模塊規范的核心要點及細節解析&#xff1a; &#x1f4e6; 一、核心語法導出&#xff08;export&#xff09; 命名導出&#xff1a;支持導出多個具名成員。export const a 1; export function b() { /* ... */ } // 或集中導出 …