邻接表存储 - 无权图的单源最短路算法(C++描述)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define js ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
vector<int> g[100];
queue<int> qu;
int dist[100];
int path[100];
int main(){
    int n;
    cin>>n;
    memset(path,-1,sizeof(path));
    while(n--){
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
    }
    int m;
    bfs(m);
}
void bfs(int start){
    qu.push(start);
    while(!qu.empty()){
        int now=qu.front();
        qu.pop();
        for(auto nxt:g[now]){
            if(dist[nxt]==-1){
                dist[nxt]=dist[now]+1;
                path[nxt]=now;
                qu.push(nxt);
            }
        }
    }
}

Dijkstra算法:单源最短路(未使用堆优化)

#include<bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
typedef long long ll;
struct Edge{
    int z,val,nexty;
}edge[200005];
int head[20000];
int cnt=0;
//链式前向星存边
void add(int a,int b,int c){
    cnt++;
    edge[cnt].z=b;
    edge[cnt].val=c;
    edge[cnt].nexty=head[a];
    head[a]=cnt;
}
int main(){
    bool vis[20000]={0};
    ll dis[20000];
    int n,m,s;
    int a,b,c;
    cin>>n>>m>>s;
    for(int i=1;i<=n;i++){
        dis[i]=0x7fffffff;
    }
    for(int i=0;i<m;i++){
        cin>>a>>b>>c;
        add(a,b,c);
    }
    int now=s;
    dis[s]=0;//起点
    ll minn=0x7fffffff;
    while(!vis[now]){
        vis[now]=1;
        for(int i=head[now];i;i=edge[i].nexty){
            if(!vis[edge[i].z]&&dis[edge[i].z]>dis[now]+edge[i].val){
                dis[edge[i].z]=dis[now]+edge[i].val;
            }
        }
        minn=0x7fffffff;
        for(int i=1;i<=n;i++){
            if(!vis[i]&&minn>dis[i]){
                minn=dis[i];
                now=i;
            }
        }
    }
    for(int i=1;i<=n;i++) cout<<dis[i]<<" ";
}

Dijkstra算法:单源最短路(使用堆优化)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Edge{
    int z,val,nexty;
}edge[1000000];
int head[200000];
ll dis[200000];
bool vis[200000]={0};
int cnt=0;
//链式前向星存边
inline void add(int a,int b,int c){
    cnt++;
    edge[cnt].z=b;
    edge[cnt].val=c;
    edge[cnt].nexty=head[a];
    head[a]=cnt;
}
struct node{
    int dis;
    int pos;
    bool operator<(const node &x)const{
        return x.dis<dis;
    }
};
priority_queue<node> q;
int main(){
    int n,m,s;
    int a,b,c;
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=n;i++){
        dis[i]=0x7fffffff;
    }
    for(int i=0;i<m;i++){
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
    }
    dis[s]=0;//起点
    q.push((node){0,s});
    while(!q.empty()){
        node tmp=q.top();
        q.pop();
        int x=tmp.pos,d=tmp.dis;
        if(vis[x]) continue;
        vis[x]=1;
        for(int i=head[x];i;i=edge[i].nexty){
            int y=edge[i].z;
            if(dis[y]>dis[x]+edge[i].val){
                dis[y]=dis[x]+edge[i].val;
                if(!vis[y]){
                    q.push((node){dis[y],y});
                }
            }
        }
    }
    for(int i=1;i<=n;i++) printf("%d ",dis[i]);
}

Floyd算法:多源最短路

#include<bits/stdc++.h>
#include<algorithm>
#define int long long
using namespace std;
int dis[105][105];
typedef long long ll;
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int n,m,k;
	cin>>n>>m>>k;
	//先初始化dis数组为无穷大 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			dis[i][j]=0x7fffffff;
		}
	}
	//读入图,更新距离 
	for(int i=0;i<m;i++){
		int a,b,c;
		cin>>a>>b>>c;
		dis[a][b]=min(dis[a][b],c);//对付重边 
	}
	//三重循环更新最小距离 
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			if(i==k||dis[i][k]==0x7fffffff) continue;
			for(int j=1;j<=n;j++){
				if(dis[i][k]+dis[k][j]<dis[i][j]){
					dis[i][j]=dis[i][k]+dis[k][j];
				}
			}
		}
	}
	while(k--){
		int a,b;
		cin>>a>>b;
		if(dis[a][b]==0||dis[a][b]==0x7fffffff){
			cout<<"Nothing to say!"<<endl;
		}else{
			cout<<dis[a][b]<<endl;
		}
	}
	return 0;
}

SPFA算法:可以求负权图

用dis数组记录源点到有向图上任意一点距离,其中源点到自身距离为0,到其他点距离为INF。将源点入队,并重复以下步骤:

  • 队首x出队
  • 遍历所有以队首为起点的有向边(x,i),若dis[x]+w(x,i)<dis[i],则更新dis[i]
  • 如果点i不在队列中,则i入队
  • 若队列为空,跳出循环;否则执行1
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define js ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
typedef long long ll;
struct Edge{
    int to,val,nexty;
}edge[200005];
int head[100005],cnt;
void addedge(int u,int v,int val){
    cnt++;
    edge[cnt].to=v;
    edge[cnt].val=val;
    edge[cnt].nexty=head[u];
    head[u]=cnt;
}
int n,m,s;
int dis[100005],vis[100005];
const int inf=0x7fffffff;
void spfa();
signed main(){
    cin>>n>>m>>s;
    for(int i=1;i<=m;i++){
        int u,v,val;
        cin>>u>>v>>val;
        addedge(u,v,val);
    }
    spfa();
    for(int i=1;i<=n;i++){
        if(i==s) cout<<0<<" ";
        else cout<<dis[i]<<" ";
    }
    return 0;
}
void spfa(){
    queue<int> qu;
    for(int i=1;i<=n;i++){
        dis[i]=inf;
        vis[i]=0;
    }
    qu.push(s);dis[s]=0;vis[s]=1;
    //vis[i]表示i是否在队列中
    while(!qu.empty()){
        int u=qu.front();
        qu.pop();
        vis[u]=0;
        for(int i=head[u];i;i=edge[i].nexty){
            int v=edge[i].to;
            if(dis[v]>dis[u]+edge[i].val){
                dis[v]=dis[u]+edge[i].val;
                if(vis[v]==0){
                    vis[v]=1;
                    qu.push(v);
                }
            }
        }
    }
}