最短路径裸题 ,用了dijkstra , Floy , Bellman-Floy 算法实现,纯粹练手
Dijkstra_数组模拟邻接表_优先队列STL实现
#include <cstdio> #include <cstring> #include <queue> #include <utility> #define N 210 #define M 2020 //有1000条无向边,要转化为两条有向边保存 #define INF 0x3f3f3f3f using namespace std; typedef pair<int,int> pii; struct edge {int u,v,w,next;}e[M]; int first[N],d[N],done[N]; int n,m,s,t; void input() { memset(first,-1,sizeof(first)); m*=2; //m条无向边相当于2*m条有向边处理 for(int i=0; i<m; i+=2) //无向图,邻接表,每输入一边无向边相当于有两条有向边 { int u; scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w); e[i+1].u=e[i].v; e[i+1].v=e[i].u; e[i+1].w=e[i].w; //先处理第一条有向边<u,v>,即e[i]里面的信息 u=e[i].u; e[i].next=first[u]; first[u]=i; //后处理第二条有向边<v,u>,即e[i+1]里面的信息 u=e[i+1].u; e[i+1].next=first[u]; first[u]=i+1; } scanf("%d%d",&s,&t); /* printf("打印邻接表:\n"); for(int i=0; i<n; i++) { printf("%d:",i); for(int k=first[i]; k!=-1; k=e[k].next) { int v=e[k].v , w=e[k].w; printf(" %d\\%d",v,w); } printf("\n"); } printf("************************\n"); */ return ; } void dij_priority_queue() { priority_queue< pii,vector<pii>,greater<pii> > q; //优先队列需要三个参数,1.元素类型 2.容器类型 3.比较算子 memset(d,0x3f,sizeof(d)); d[s]=0; memset(done,0,sizeof(done)); q.push(make_pair(d[s],s)); //将一个二元组(d[s],s)放入优先队列 while(!q.empty()) { pii x; x=q.top(); q.pop(); //读入优先队列优先级最高的元素并且将其出队 int u=x.second; //得到二元组的第二个元素,也就是顶点的标号 if(done[u]) continue; //这个顶点已经算得最短路,直接抛弃 done[u]=1; //记得标记 for(int k=first[u]; k!=-1; k=e[k].next) //遍历u顶点的邻接表 { int v=e[k].v , w=e[k].w ; if( d[u]+w < d[v] ) //可以松弛 { d[v]=d[u]+w; q.push(make_pair(d[v],v)); //松弛成功的入队 } } } if(d[t]==INF) printf("-1\n"); else printf("%d\n",d[t]); return ; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { input(); dij_priority_queue(); //使用优先队列的dij求最短路 } return 0; }
Dijkstra算法_邻接矩阵
//dij算法,单源最短路径 //注意细节,可能有重边,取最小的那个 #include <stdio.h> #include <string.h> #define N 210 #define INF 1000000000 int S,V; int n,m; int g[N][N]; int cov[N],d[N]; void DIJ() { int nn,min,k,i; d[S]=0; for(nn=1; nn<n; nn++) //个数,还要求出源点S到其余所有点的最短路径 { min=INF; k=S; for(i=0; i<n; i++) //扫描所有的点 if(!cov[i] && d[i]<min) { k=i; min=d[i]; } cov[k]=1; for(i=0; i<n; i++) //松弛操作 if(!cov[i] && d[i] > min+g[k][i]) d[i]=min+g[k][i]; } } int main() { int i,j,u,v,w; while(scanf("%d%d",&n,&m)!=EOF) { memset(cov,0,sizeof(cov)); for(i=0; i<n; i++) for(d[i]=INF,j=0; j<n; j++) g[i][j]=INF; for(i=1; i<=m; i++) { scanf("%d%d%d",&u,&v,&w); if(g[u][v] > w) //判断重边 g[u][v]=g[v][u]=w; } scanf("%d%d",&S,&V); DIJ(); if(d[V]==INF) printf("-1\n"); else printf("%d\n",d[V]); } return 0; }
Floy算法
#include <stdio.h> #include <string.h> #define N 210 #define INF 1000000000 int d[N][N]; int n,m,S,V; void Floy() { int i,j,k; for(k=0; k<n; k++) for(i=0; i<n; i++) for(j=0; j<n; j++) if(d[i][j] > d[i][k]+d[k][j]) d[i][j]=d[i][k]+d[k][j]; return ; } int main() { int i,j,u,v,w; while(scanf("%d%d",&n,&m)!=EOF) { for(i=0; i<n; i++) for(j=0; j<n; j++) if(i==j) d[i][j]=0; else d[i][j]=INF; for(i=1; i<=m; i++) { scanf("%d%d%d",&u,&v,&w); if(w<d[u][v]) d[u][v]=d[v][u]=w; } scanf("%d%d",&S,&V); Floy(); if(d[S][V]==INF) printf("-1\n"); else printf("%d\n",d[S][V]); /* for(i=0; i<n; i++) { for(j=0; j<n; j++) printf("%d ",d[i][j]); printf("\n"); } */ } return 0; }
Bellman-Floy算法
#include <stdio.h> #include <string.h> #define N 210 #define INF 1000000000 int g[N][N],d[N]; int S,V,n,m; void Bellman_Floy() { int nn,i,j; d[S]=0; for(nn=1; nn<n; nn++) //定点数为n,要做n-1次 //枚举所有的边i->j ,然后进行松弛操作 for(i=0; i<n; i++) for(j=0; j<n; j++) if( d[j] > d[i]+g[i][j]) d[j]=d[i]+g[i][j]; } int main() { int i,j,u,v,w; while(scanf("%d%d",&n,&m)!=EOF) { for(i=0; i<n; i++) for(d[i]=INF,j=0; j<n; j++) g[i][j]=INF; for(i=1; i<=m; i++) { scanf("%d%d%d",&u,&v,&w); if(w<g[u][v]) g[u][v]=g[v][u]=w; } scanf("%d%d",&S,&V); Bellman_Floy(); if(d[V]==INF) printf("-1\n"); else printf("%d\n",d[V]); } return 0; }