Dijkstra算法
Dijkstra算法适用于边权为正的情况,可以求得从单个源点出发,到达所有节点的最短路
本篇借鉴刘汝佳紫书代码模板
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
#define LL long long
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
struct Edge{
int from,to,dist;
Edge(int u,int v,int d):from(u),to(v),dist(d){}
};
struct HeapNode{
int d,u;
bool operator < (const HeapNode& rhs)const{
return rhs.d<d;
}
};
struct Dijkstra{
int n,m;
vector<Edge>edges;
vector<int>G[maxn];
bool flag[maxn];
int d[maxn];
void init(int n){
this->n=n;
for(int i=0;i<n;i++)G[i].clear();
edges.clear();
}
void AddEgde(int from,int to,int dist){
edges.push_back(Edge(from,to,dist));
m=edges.size();
G[from].push_back(m-1);
}
void dijkstra(int s){
priority_queue<HeapNode>Q;
for(int i=0;i<=n;i++)d[i]=inf;
d[s]=0;
memset(flag,0,sizeof(flag));
Q.push((HeapNode){0,s});
while(!Q.empty()){
HeapNode x=Q.top();Q.pop();
int u=x.u;
if(flag[u])continue;
flag[u]=1;
for(int i=0;i<G[u].size();i++){
Edge& e=edges[G[u][i]];
if(d[e.to]>d[u]+e.dist){
d[e.to]=d[u]+e.dist;
Q.push((HeapNode){d[e.to],e.to});
}
}
}
}
};
int main(){
Dijkstra Gra;
int n,m,s,u,v,w;
scanf("%d%d%d",&n,&m,&s);
Gra.init(n);
for(int i=0;i<m;i++){
scanf("%d%d%d",&u,&v,&w);
Gra.AddEgde(u,v,w);
}
Gra.dijkstra(s);
for(int i=1;i<=n;i++)printf("%d ",Gra.d[i]);
}
Bellman_ford 算法
Bellman_ford算法适用于存在负权路的图,时间复杂度为O(nm),用FIFO队列代替循环检查后就变成了经典的SPFA算法。理论上复杂度仍然为O(nm),但实践中往往能在很快的情况下求出最短路。
该算法另外一个应用就是求出图中是否有负圈。实现时只需记录对一个点的松弛次数是否大于等于n即可。
缺点是spfa算法容易被数据卡,并且使用vector+结构体的存图方式常数极大,但适用性及可读性十分可观,因此仍使用上述方法存图
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn=2005;
const int inf=0x3f3f3f3f;
struct Edge{
int from,to,dist;
Edge(int u,int v,int w):from(u),to(v),dist(w){};
};
struct Graph{
int cnt[maxn],n,m,dis[maxn];
bool inq[maxn];
vector<int>G[maxn];
vector<Edge>edges;
void init(int n){
this->n=n;
for(int i=1;i<=n;i++)G[i].clear();
edges.clear();
}
void Addedge(int u,int v,int w){
edges.push_back(Edge(u,v,w));
m=edges.size();
G[u].push_back(m-1);
}
bool bellman_ford(int s){
queue<int>q;
memset(inq,0,sizeof(inq));
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++)dis[i]=inf;
dis[s]=0,inq[s]=1,cnt[s]=1;
q.push(s);
while(q.size()){
int u=q.front();q.pop();
inq[u]=0;
for(int i=0;i<G[u].size();i++){
Edge& e=edges[G[u][i]];
if(dis[u]<inf&&dis[e.to]>dis[u]+e.dist){
dis[e.to]=dis[u]+e.dist;
if(++cnt[e.to]>=n)return 1;
if(!inq[e.to]){
q.push(e.to);
inq[e.to]=1;
}
}
}
}
return 0;
}
};
int main(){
int n,m,t,u,v,w;
cin>>t;
while(t--){
Graph Gra;
scanf("%d%d",&n,&m);
Gra.init(n);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
Gra.Addedge(u,v,w);
if(w>=0)Gra.Addedge(v,u,w);
}
if(Gra.bellman_ford(1))puts("YE5");
else puts("N0");
}
}