提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
Dijkstra算法
经典例题
https://leetcode.cn/problems/network-delay-time/description/
class Solution {
public:
int networkDelayTime(vector<vector<int>>& times, int n, int k) {
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>> > q;
vector<vector<pair<int,int>>> g(n+1);
for(auto time:times){
g[time[0]].push_back({time[1],time[2]});
}
vector<int>distance(n+1,INT_MAX);
vector<bool> visited(n+1,0);
distance[k]=0;
q.push({0,k});
while(q.size()){
int tmp=q.top().second;
q.pop();
if(visited[tmp])continue;
visited[tmp]=true;
for(auto gg : g[tmp]){
int w=gg.second,v=gg.first;
if(!visited[v] && w+distance[tmp]<distance[v]){
distance[v]=w+distance[tmp];
q.push({distance[v],v});
}
}
}
int ans=0;
for(int i=1;i<=n;i++){
if(distance[i]==INT_MAX){
return -1;
}
ans=max(ans,distance[i]);
}
return ans;
}
};
A星算法
与Dijkstra算法相似,但不同的是,只想快速找到源点到目标点的最小距离。
操作上,在小根堆中比较的是源点到某点的距离+某点到目标点的预估距离。(目的为了更快向目标点靠拢);
floyd算法
得到图中任意两点之间的最短距离,多源最短路
例题:洛谷2910
#include <stdio.h>
#include <stdlib.h>
using namespace std;
#include<bits/stdc++.h>
int route[10002];
int g[101][101];
int main(){
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++)cin>>route[i];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>g[i][j];
}
}
for(int brigde=1;brigde<=n;brigde++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(g[i][j]>(g[i][brigde]+g[brigde][j])){
g[i][j]=g[i][brigde]+g[brigde][j];
}
}
}
}
int ans=0;
for(int i=0;i<m-1;i++){
ans+=g[route[i]][route[i+1]];
}
cout<<ans;
return 0;
}
Bellman-Ford
和Dijkral算法目的相同,但允许有负权边
例题:
https://leetcode.cn/problems/cheapest-flights-within-k-stops/description/
这题为了保证每轮最多使最短路边数加一,采用了cur 和 next数组
class Solution {
public:
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int k) {
vector<int> cur(n,INT_MAX);
cur[src]=0;
for(int i=0;i<=k;i++){
vector<int> next(cur);
for(auto &flight:flights){
if(cur[flight[0]]!=INT_MAX){
next[flight[1]]=min(cur[flight[0]]+flight[2],next[flight[1]]);
}
}
cur=next;
}
return cur[dst]==INT_MAX ? -1 : cur[dst];
}
};
SPFA :对Bellan-Ford的优化(队列)
但只是常数优化,时间复杂度仍为m*n
洛谷:3385
判断负环
#include <stdio.h>
#include <stdlib.h>
using namespace std;
#include<bits/stdc++.h>
typedef pair<int,int> PII;
int dis[2001];
int q[6000001];
bool enter[2001];
int cnt[2001];
vector<vector<PII> > g(2001);
int main(){
int t,n,m;
cin>>t;
while(t--){
cin>>n>>m;
for(int i=1;i<=n;i++){
dis[i]=INT_MAX;
enter[i]=0;
cnt[i]=0;
g[i].clear();
}
for(int i=0;i<m;i++){
int u,v,w;
cin>>u>>v>>w;
g[u].push_back({v,w});
if(w>=0)g[v].push_back({u,w});
}
int l=0,r=0;
q[r++]=1;
dis[1]=0;
enter[1]=true;
cnt[1]++;
int flag=1;
while(l<r){
int now=q[l++];
enter[now]=false;
for(auto &next:g[now]){
int vv=next.first,ww=next.second;
if(dis[vv]>(dis[now]+ww)){
dis[vv]=dis[now]+ww;
if(!enter[vv]){
if(cnt[vv]++ == n){
flag=0;
l=r;
break;
}
q[r++]=vv;
enter[vv]=1;
}
}
}
}
if(flag) cout<<"NO"<<'\n';
else cout<<"YES"<<'\n';
}
return 0;
}