DFS
求1到n的最短路径

vis[1]=1; dfs(1,0); void dfs(int cur,int dis) { if(dis>mini) return ; if(cur==n) { mini=min(mini,dis); return ; } for(int i=1;i<=n;i++) { if(e[cur][i]!=inf && !vis[i]) { vis[i]=1; dfs(i,dis+e[cur][i]); vis[i]=0; } } }
Dijkstra (O(n2))
求s到其他点的最短距离,无法求含负权边图
思路:用一个dis数组存1号到其他顶点的初始路程,选一条离1号最近的边,dis[2]就确定了,考虑2号顶点的出边,进行一次松弛操作,接下来继续从未选的顶点中选一条离1号最近的边,继续如上操作。

Bellman-Ford
无负环的情况可以使用

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <map> using namespace std; typedef long long ll; const int maxn=1e3+10; const int inf=1<<25; int T,n,m,cases; struct edge { int u,v,w; }a[maxn]; int path[maxn],dis[maxn]; bool Bellman(int s) { for(int i=0;i<n;i++) dis[i]=inf,path[i]=-1; dis[s]=0; for(int i=0;i<n;i++) { ///迭代n次,如果第n次还在更新,说明有负环 bool flag=0; for(int j=0;j<m;j++) { int x=a[j].u,y=a[j].v; if(dis[x]<inf && dis[x]+a[j].w<dis[y]) { dis[y]=dis[x]+a[j].w; path[y]=x; flag=1; if(i==n-1) return true;///返回真,真的存在负环 } } if(!flag) break;///如果没更新了,说明已经松弛完毕 } for(int i=0;i<n;i++) { if(i==s) continue; printf("从%d到%d距离是:%2d ", s,i,dis[i]); stack<int>q; int x=i; while(path[x]!=-1) { q.push(x); x=path[x]; } cout<<s; while(!q.empty()) { cout<<"->"<<q.top(); q.pop(); } cout<<endl; } return false; } int main() { cin>>n>>m; for(int i=0;i<m;i++) cin>>a[i].u>>a[i].v>>a[i].w; if(Bellman(0)) cout<<"存在负环"<<endl; else cout<<"不存在负环"<<endl; return 0; }

#include<bits/stdc++.h> const int inf=0x3f3f3f3f; using namespace std; int main( ) { int u[100],v[100],w[100],dis[100],n,m,ck,flag; cin>>n>>m; for(int i=1;i<=m;i++) cin>>u[i] >> v[i] >> w[i]; memset(dis,inf,sizeof(dis)); dis[1]=0; for(int k=1;k<=n-1;k++) { ck=0; ///用来标记本轮松弛操作中数组dis是否会发生更新 for(int i=1;i<=m;i++) { if(dis[v[i]]>dis[u[i]]+w[i]) { dis[v[i]]=dis[u[i]]+w[i]; ck=1; ///数组dis发生更新,改变check的值 } } if(ck==0) break; ///如果dis数组没有更新,提前退出循环结束算法 } flag=0; for(int i=1;i<=m;i++) { if(dis[v[i]]>dis[u[i]]+w[i]) flag=1; if(flag==1) printf("此图包含有负权回路 "); else { for(int i=1;i<=n;i++) printf("%d ",dis[i]); return 0; } } return 0 ; }
队列优化:每次仅对最短路估计值发生变化了的顶点的所有出边进行松弛

#include <iostream> #include <cstring> using namespace std; #define inf 0x3f3f3f3f int u[8],v[8],w[8],first[6],net[8],dis[6],vis[6]; int main() { int n,m; cin>>n>>m; memset(dis,inf,sizeof(dis)); dis[1]=0; memset(vis,0,sizeof(vis)); memset(first,-1,sizeof(first)); for(int i=1;i<=m;i++) { cin>>u[i]>>v[i]>>w[i]; net[i]=first[u[i]]; first[u[i]]=i; } int que[101],head=1,tail=1; que[tail++]=1; vis[1]=1; while(head<tail) { int k=first[que[head]]; while(k!=-1) { if(dis[v[k]]>dis[u[k]]+w[k]) { dis[v[k]]=dis[u[k]]+w[k]; if(!vis[v[k]]) { que[tail]=v[k]; tail++; vis[v[k]]=1; } } k=net[k]; } vis[que[head]]=0; head++; } for(int i=1; i<=n; i++) cout<<dis[i]<<" "; return 0; }
SPFA
求s到t的最短路

#include <iostream> #include <queue> #include <algorithm> #include <cstring> using namespace std; #define inf 0x3f3f3f3f queue<int>q; const int maxn=1e5; int dis[maxn],vis[maxn],cost[maxn]; int from[maxn],to[maxn]; int net[maxn],head[maxn]; int n,m,s,t; int k; ///边数 void add(int u,int v,int w) { ///from表示边的出发点,to为边的到达点 from[++k]=u; to[k]=v; net[k]=head[u]; head[u]=k; cost[k]=w; } void spfa(int s) { ///以s为起点的所有点的最短路 for(int i=1;i<=n;i++) dis[i]=inf; memset(vis,0,sizeof(vis)); vis[s]=1; dis[s]=0; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];~i;i=net[i]) { int v=to[i]; if(dis[v]>dis[u]+cost[i]) { dis[v]=dis[u]+cost[i]; if(!vis[v]) q.push(v);vis[v]=1; } } } } int main( ) { k=0; memset(head,-1,sizeof(head)); cin>>n>>m>>s>>t; for(int i=1;i<=m;i++) { int u,v,w; cin>>u>>v>>w; add(u,v,w); add(v,u,w); } spfa(s); cout<<dis[t]; return 0; }

#include <bits/stdc++.h> #define maxn 500009 using namespace std; #define inf 0x3f3f3f3f int dis[maxn],net[maxn],to[maxn],w[maxn],head[maxn]; int n,m,s; queue<int> q; int tot=0; bool vis[maxn]; void add(int x,int y,int z) { net[++tot]=head[x]; head[x]=tot; w[tot]=z; to[tot]=y; } void spfa(int u) { memset(dis,inf,sizeof(dis)); dis[u]=0; memset(vis,0,sizeof(vis)); vis[u]=1; q.push(u); while(!q.empty()) { int x=q.front(); q.pop(); vis[x]=0; for(int i=head[x];i;i=net[i]) { int y=to[i]; if(dis[x]+w[i]<dis[y]) { dis[y]=dis[x]+w[i]; if(!vis[y]) vis[y]=1,q.push(y); } } } } int main( ) { cin>>n>>m>>s;///s为起点 for(int i=1;i<=m;i++) { int x,y,z; cin>>x>>y>>z; add(x,y,z); } spfa(s); for(int i=1;i<=n;i++) printf("%d ",dis[i]); return 0; }
Floyd-Warshall
求任意两个点之间的最短路径

void Floyd() { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { path[i][j]=-1; if(i==j) e[i][j]=0; else e[i][j]=inf; } } for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(e[i][j]>e[i][k]+e[k][j]) { path[i][j]=k; e[i][j]=e[i][k]+e[k][j]; } } } } } void print(int u,int v) { if(path[u][v]==-1) return ; print(u,path[u][v]); cout<<path[u][v]<<"->"; }