题目
给你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)
Output
输出 一行有两个数, 最短距离及其花费。
- 一开始用Floyd算法写了代码,但提交便超时,因此苦苦不能解决(还是太菜了!)
- 后面用Dijkstra算法解决
AC代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define INF 1e6+5
using namespace std;
int G[1005][1005]; //记录两点间距离
int cost[1005][1005]; //记录两点间花费
int vis[10005];
int d[1005]; //用来记录起点到每条边的最短路径
int co[1005]; //用来记录起点到每条边的花费
int n,m; //点 边
int s,t;
void dijkstra()
{
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++) d[i]=INF,co[i]=INF;
co[s]=d[s]=0; //把起点赋初值零,其余不变
for(int i=1;i<=n;i++){
int x,m=INF; //x用来记录每次循环数组d中值最小的位置
for(int y=1;y<=n;y++) if(!vis[y]&&d[y]<=m) m=d[y],x=y;
vis[x]=1;
for(int y=1;y<=n;y++){
if(d[y]>G[x][y]+d[x]){
d[y]=G[x][y]+d[x];
co[y]=cost[x][y]+co[x];
}else if(d[y]==G[x][y]+d[x]&&co[y]>cost[x][y]+co[x]){ //当路径一致时判断花费
co[y]=cost[x][y]+co[x];
}
}
}
}
int main()
{
while(scanf("%d %d",&n,&m)==2&&(n||m))
{
for(int i=1;i<=n;i++){ //全部赋初值INF
for(int j=1;j<=n;j++){
G[i][j]=INF;
cost[i][j]=INF;
}
}
for(int i=1;i<=m;i++){
int a,b,d,p;
scanf("%d %d %d %d",&a,&b,&d,&p);
if(G[a][b]>d){ //去重,保证路径最短
G[a][b]=G[b][a]=d;
cost[a][b]=cost[b][a]=p;
}
if(G[a][b]==d&&cost[a][b]>p){ //路径一致则保证花费最低
cost[a][b]=cost[b][a]=p;
}
}
scanf("%d %d",&s,&t);
dijkstra();
printf("%d %d\n",d[t],co[t]);
}
return 0;
}