最短路径算法
1.Floyed(N3)
#include<iostream> #include<cstring> #define MAXN 1000 using namespace std; int n,m,s,e,d; bool vis[MAXN][MAXN]; int dis[MAXN][MAXN],w[MAXN][MAXN],pre[MAXN][MAXN]; inline void Floyed() { for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=k&&i!=j&&k!=j&&dis[i][k]+dis[k][j]<dis[i][j]) { dis[i][j]=dis[i][k]+dis[k][j]; pre[i][j]=pre[k][j]; } } void Print(int x) { if(pre[s][x]==0) return; Print(pre[s][x]); cout<<"—>"<<x; }//输出路径需要pre数组,储存上一级位置 //弗洛伊德算法,O(N*N*N),可处理负边权,可以改动判断连通图 //vis[i][j]=vis[i][j]||(vis[i][k]&&dis[k][j]) int main() { memset(pre,0,sizeof(pre)); memset(dis,0x7f,sizeof(dis)); cin>>n>>m; for(int i=1;i<=m;i++) { cin>>s>>e>>d; dis[s][e]=d; dis[e][s]=d; pre[s][e]=s; pre[e][s]=e; } cin>>s>>e;//起始点和结束点 Floyed(); cout<<s; Print(e); cout<<endl<<dis[s][e]; return 0; }
2.Dijkstra朴素算法(N2)
#include<iostream> #include<cstring> #define MAXN 3000 #define INF 0xfffffff using namespace std; int n,m,s,e,d,k,minn,st,se; bool vis[MAXN]; int dis[MAXN][MAXN],c[MAXN]; //待添加路径输出程序 int main() { memset(vis,0,sizeof(vis)); memset(dis,0x7f,sizeof(dis)); cin>>n>>m>>s>>e; for(int i=1;i<=m;i++) { cin>>st>>se>>d; dis[st][se]=d; dis[se][st]=d; } //初始化 for(int i=1;i<=n;i++) c[i]=dis[s][i]; vis[s]=true; //Dijkstra for(int i=1;i<=n-1;i++) { minn=INF; k=0; for(int j=1;j<=n;j++) if(!vis[j]&&c[j]<minn) { minn=c[j]; k=j; } if(k==0) break; vis[k]=true; for(int j=1;j<=n;j++) if(c[k]+dis[k][j]<c[j]) c[j]=dis[k][j]+c[k]; } cout<<c[e]<<endl; return 0; }
3.Dijkstra堆优化
#include<bits/stdc++.h> #include<cstring> #define MAXN 1003000 #define INF 0xfffffff using namespace std; int n,m,s,t,a,b,c,cnt=0; struct egde { int to; int dis; int next; }e[MAXN]; struct node { int dis; int pos; bool operator < (const node &x) const { return x.dis<dis; } }; int head[MAXN],dist[MAXN],vis[MAXN]; priority_queue<node> q; void addedge(int u,int v,int w) { cnt++; e[cnt].dis=w; e[cnt].to=v; e[cnt].next=head[u]; head[u]=cnt; }; void Dijkstra() { dist[1]=0; q.push({0,1}); 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=e[i].next) { int y=e[i].to; if(dist[y]>dist[x]+e[i].dis) { dist[y]=dist[x]+e[i].dis; q.push({dist[y],y}); } } } } int main() { cin>>n>>m; for(int i=1;i<=m;i++) { cin>>a>>b>>c; addedge(a,b,c); addedge(b,a,c); } memset(vis,0,sizeof(vis)); memset(dist,0x3f,sizeof(dist)); Dijkstra(); cout<<dist[n]; return 0; }
4.Bell-Ford算法(N*M)
#include<iostream> #include<cstring> #define MAXN 1000 #define INF 0xfffffff using namespace std; int n,m,s,e,d; struct line { int dist; int start; int end; }w[MAXN]; bool vis[MAXN][MAXN]; int dis[MAXN]; int main() { memset(vis,0,sizeof(vis)); memset(dis,0x7f,sizeof(dis)); cin>>n>>m; for(int i=1;i<=m;i++) { cin>>s>>e>>d; w[i].dist=d; w[i].start=s; w[i].end=e; } cin>>s>>e; dis[s]=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { int u=w[j].start; int v=w[j].end; if(dis[u]+w[j].dist<dis[v]) dis[v]=dis[u]+w[j].dist; /*v=w[j].start; u=w[j].end; if(dis[u]+w[j].dist<dis[v]) dis[v]=dis[u]+w[j].dist;*///反向计算双向图 } cout<<dis[e]; return 0; }
5.SPFA(K*M)//稠密图会变慢,不太稳定,容易被卡,但很强大
#include<iostream> #include<queue> #include<cstring> #define maxn 1005 #define maxm 2005 #define inf 0x3f3f3f using namespace std; queue<int> q; int n,m,u,v,w,s,t,cnt=0; int head[maxn],vis[maxn],dist[maxn]; struct node { int dis; int next; int to; }e[maxm]; void addedge(int u,int v,int w) { cnt++; e[cnt].to=v; e[cnt].dis=w; e[cnt].next=head[u]; head[u]=cnt; } void spfa(int s) { dist[s]=0; vis[s]=true; q.push(s); while(!q.empty()) { int x=q.front(); q.pop(); vis[x]=false; for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if(dist[y]>(dist[x]+e[i].dis)) { dist[y]=dist[x]+e[i].dis; if(vis[y]==false) { q.push(y); vis[y]=true; } } } } } int main() { cin>>n>>m>>s>>t; for(int i=1;i<=m;i++) { cin>>u>>v>>w; addedge(u,v,w); } memset(vis,0,sizeof(vis)); memset(dist,0x3f,sizeof(dist)); spfa(s); cout<<dist[t]; return 0; }

浙公网安备 33010602011771号