最短路
Problem Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?
Input 输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。 输入保证至少存在1条商店到赛场的路线。
Output 对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
Sample Input 2 1 1 2 3 3 3 1 2 5 2 3 5 3 1 2 0 0
Sample Output 3 2
附上 floyd , dijkstra 和 spfa邻接表 三种算法 :
floyd : 缺点 :时间复杂度高O(N^3);
优点 : 求出了所有点两两间的最短距离 ;
dijkstra :
缺点 : 只能求出一点到其余各点的最短距离;
优点 : 时间复杂度低O(N^2);
spfa邻接表 :
两点间的关系都可以有临界表处理,时间复杂度较低; 可以处理开不了二维数组的大数据;
根据实际情况,做最佳选择
floyd :
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; int mapp[110][110]; int N,M; void floyd() { int i,j,l; for(l=1;l<=N;l++) { for(i=1;i<=N;i++) { if(mapp[i][l]==INF) continue; for(j=1;j<=N;j++) { mapp[i][j]=min(mapp[i][j],mapp[i][l]+mapp[l][j]);//更新 i ,j 两点间的最短距离 } } } printf("%d\n",mapp[1][N]); } int main() { int i,j; int a,b,c; while(scanf("%d%d",&N,&M)!=EOF) { if(N==0&&M==0) break; for(i=1;i<=N;i++) { mapp[i][i]=0; for(j=1;j<i;j++) mapp[i][j]=mapp[j][i]=INF; } while(M--) { scanf("%d%d%d",&a,&b,&c); if(mapp[a][b]>c)//判断是否有重边 mapp[a][b]=mapp[b][a]=c; } floyd(); } return 0; }dijkstra :
#include<cstdio> #include<cstring> const int INF=0x3f3f3f3f; int mapp[110][110]; int vis[110];//标记点 int dis[110]; int N,M; void dijkstra() { int i,j; int ml; int ans;//记录最小距离 memset(vis,0,sizeof(vis));//初始化标记 for(i=1;i<=N;i++) dis[i]=mapp[1][i];//当前所有的点到商店的最短距离 vis[1]=1;//标记 1 点 for(i=2;i<=N;i++) { ans=INF; for(j=1;j<=N;j++) { if(vis[j]==0&&ans>dis[j]) { ans=dis[j];//记录小到 i 点的最短距离 ml=j;//记录小到 i 点的距离最短的点 } } vis[ml]=1;//把该点标记 for(j=1;j<=N;j++) { if(vis[j]==0&&dis[ml]+mapp[ml][j]<dis[j]) dis[j]=dis[ml]+mapp[ml][j];//更新到 1 点的最短距离 } } printf("%d\n",dis[N]);//输出赛场到商店的最短距离 } int main() { int i,j; int a,b,c; while(scanf("%d%d",&N,&M)!=EOF) { if(N==0&&M==0) break; for(i=1;i<=N;i++) { mapp[i][i]=0; for(j=1;j<i;j++) mapp[i][j]=mapp[j][i]=INF; } for(i=1;i<=M;i++) { scanf("%d%d%d",&a,&b,&c); if(mapp[a][b]>c)//建议养成习惯加上可能会有重边的的情况 mapp[a][b]=mapp[b][a]=c; } dijkstra(); } return 0; }spfa邻接表 :
#include<cstdio> #include<algorithm> #include<queue> #include<cstring> using namespace std; const int INF=0x3f3f3f3f; struct node { int to,val,next; }st[10011]; int head[110]; int dis[110]; int vis[110]; int num; int N,M; void init()//初始化 { num=0; memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); } void add(int x,int y,int z) { st[num].to=y; st[num].val=z; st[num].next=head[x]; head[x]=num++; } /*void add(int x,int y,int z)//同上面的效果一样,两种临界表的建立方式 { node E={y,z,head[x]}; st[num]=E; head[x]=num++; }*/ void spfa() { queue <int> q; while(!q.empty()) q.pop(); int i,j; fill(dis+1,dis+N+1,INF); dis[1]=0; q.push(1); vis[1]=1;//标记 while(!q.empty()) { int w=q.front(); q.pop(); vis[w]=0;//释放 for(i=head[w];i!=-1;i=st[i].next) { int ml=st[i].to;//遍历以 w 为起点的所有边的终点 ml if(dis[ml]>dis[w]+st[i].val) { dis[ml]=dis[w]+st[i].val; if(!vis[ml])//优化 不会有多余的点进队列 { vis[ml]=1; q.push(ml); } } } } printf("%d\n",dis[N]);//1到N的最短距离 } int main() { int a,b,c; while(scanf("%d%d",&N,&M)!=EOF) { if(N==0&&M==0) break; init(); while(M--) { scanf("%d%d%d",&a,&b,&c); add(a,b,c);//建立临界表 add(b,a,c); } spfa(); } return 0; }