Problem Description
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
Input
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)
(1<n<=1000, 0<m<100000, s != t)
Output
输出 一行有两个数, 最短距离及其花费。
Sample Input
3 2 1 2 5 6 2 3 4 5 1 3 0 0
Sample Output
9 11狄克斯特拉算法的初级应用,具体解释看代码#include<stdio.h> #include<functional> #include<vector> #include<queue> #include<math.h> #include<cstring> #include<algorithm> #include<iostream> #define INF 9999999 using namespace std; int dis[1010][1010][2];//存原始数据 int n,m; int di(int ks,int js) { int pu[1010][2]; int s[1010]; int t=0; for(int i=1;i<=n;i++) { pu[i][0]=dis[ks][i][0];//距离初始化 pu[i][1]=dis[ks][i][1];//花费初始化 s[i]=0; } s[ks]=1;//表示判断过了 for(int i=1;i<=n;i++) { int mi=INF; int mia=INF; int u; for(int j=1;j<=n;j++) { if(s[j]==0&&pu[j][0]<=mi)//取距离最小 { if(pu[j][0]==mi) { if(pu[j][1]<mia)//距离相同取花费最小 mia=pu[j][1],mi=pu[j][0],u=j; } else { mia=pu[j][1],mi=pu[j][0],u=j; } } } s[u]=1; for(int j=1;j<=n;j++) { if(s[j]==0) { if(dis[u][j][0]<INF&&pu[u][0]+dis[u][j][0]<=pu[j][0])//修改没有判断过的点距离ks的最短距离和花费 { if(pu[u][0]+dis[u][j][0]==pu[j][0]) { if(pu[u][1]+dis[u][j][1]<pu[j][1]) { pu[j][1]=pu[u][1]+dis[u][j][1]; } } else { pu[j][1]=pu[u][1]+dis[u][j][1]; pu[j][0]=pu[u][0]+dis[u][j][0]; } } } } } printf("%d %d\n",pu[js][0],pu[js][1]);//输出 } int main() { while(~scanf("%d %d",&n,&m)) { if(n==0||m==0) break; memset(dis,INF,sizeof(dis)); for(int i=0;i<m;i++) { int a,b,c,d; scanf("%d%d%d%d",&a,&b,&c,&d); if(dis[a][b][0]>c)//注意,这里要判断存入的是否最优 { dis[a][b][0]=c; dis[a][b][1]=d; dis[b][a][0]=c; dis[b][a][1]=d; } else if(dis[a][b][0]==c&&dis[a][b][1]>d) { dis[a][b][0]=c; dis[a][b][1]=d; dis[b][a][0]=c; dis[b][a][1]=d; } } int a,b; scanf("%d%d",&a,&b); di(a,b); } return 0; }