1.Floyd
由于算法时间复杂度是n^3的,一般不常用,但在无向图最小环中可以用到
设f[i][j]表示i和j之间,经过k条边的最短路径 得到状态转移方程如下
for(register int k(1) ; k<=n ; k=-~k){
for(register int i(1) ; i<=n ; i=-~i){
for(register int j(1) ; j<=n ; j=-~j){
f[i][j] = min(f[i][j],f[i][k]+f[k][j]);
f[j][i] = f[i][j];
}
}
}
2.Dijkstra
基于贪心的一种最短路算法,也是现在竞赛常用的算法用堆优化后时间复杂度O(nlogm)
用dis[u]表示已经找到的源点s到u的最短距离,如果dis[v] > dis[u] + w,用dis[u] + w更新dis[v]
用pair,优先队列优化 但注意,只能不能处理带负边权的图
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48) ; ch=getchar();}
return x*f;
}
const int M = 500010;
const int inf = 2147483647;
int n,m,s;
int cnt,head[M],vis[M];
long long dis[M];
struct egde{
int to,nxt,w;
}e[M];
typedef pair<int,int> pir;
priority_queue<pir,vector<pir>,greater<pir> >q;
void add(int u,int v,int w){
e[++cnt].w = w;
e[cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
void dij(int s){
for(register int i(1) ; i<=M-1 ; i=-~i) dis[i] = inf; //初始化为正无穷
dis[s] = 0; //自己到自己的距离为0
q.push(pir(0,s));
while(!q.empty()){
int f = q.top().first,u = q.top().second;
q.pop();
if(f!=dis[u]) continue;
for(register int i(head[u]) ; i ; i=e[i].nxt){
int v=e[i].to,w=e[i].w;
if(dis[v] > dis[u]+w){ //更新
dis[v] = dis[u]+w;
q.push(pir(dis[v],v)); //加入队列
}
}
}
}
int main(){
n=read();m=read();s=read();
for(register int i(1) ; i<=m ; i=-~i){
int u,v,w;
u=read();v=read();w=read();
add(u,v,w);
}
dij(s);
for(register int i(1) ; i<=n ; i=-~i) printf("%lld ",dis[i]);
return 0;
}
3.spfa 他已经死了 不不不,在有负边权的情况下或者别的算法中仍然能用到(但最短路尽量不用)
也是一种贪心算法,每次从队首取出一个节点x,遍历与x相通的节点y,更新最小值
#include<bits/stdc++.h>
using namespace std;
const int inf = 2147483647;
int head[100010],dis[100010];
int n,m,s;
int vis[500010];
struct edge{
int to,next,w;
}e[500100];
int cnt=0;
void add(int u,int v,int w){
cnt++;
e[cnt].to = v;
e[cnt].w = w;
e[cnt].next = head[u];
head[u] = cnt;
}
queue<int>q;
void spfa(int s){
for(int i=1 ; i<=n ; i++){
dis[i] = inf;
}
q.push(s);
vis[s] = 1;
dis[s] = 0;
while(!q.empty()){
int u=q.front();
vis[u]=0;
q.pop();
for(int i=head[u] ; i ; i=e[i].next){
int v=e[i].to;
int w=e[i].w;
if(dis[v]>dis[u]+w){
dis[v] = dis[u]+w;
if(vis[v]==0){
q.push(v);
vis[v] = 1;
}
}
}
}
return;
}
int main(){
scanf("%d%d%d",&n,&m,&s);
for(int i=1 ; i<=m ; i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
spfa(s);
for(int i=1 ; i<=n ; i++){
if(dis[i]!=inf){
printf("%d ",dis[i]);
}
else{
printf("%d ",inf);
}
}
return 0;
}