问题来源:hdu-3790
给你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
输出 一行有两个数, 最短距离及其花费。
Sample Input
3 2
1 2 5 6
2 3 4 5
1 3
0 0
Sample Output
9 11
源代码:
#include<stdio.h>
#include<string.h>
#define MAX 1006
#define INF 999999999
int map[MAX][MAX] , cost[MAX][MAX] , mark[MAX] , dis[MAX] , value[MAX];
//map[i][j]存储双向地图,存储i点到j点的距离
//cost[i][j]存储i点到j点的花费
//mark[i]标志i点手否被更新过
//dis[i]是i点到源点s的最短距离
//value[i]是i点到源点s的最短花费
void Dijstra( int map[][MAX] , int N , int s , int t );
int main( ){
int N , M;
int a , b , c , d , s , t;
while( ~scanf("%d%d",&N,&M) && N+M!=0 ){
for( int i=1 ; i<=N ; i++ )
for( int j=1 ; j<=N ; j++ ){
map[i][j] = cost[i][j] = INF; //输入前初始化
map[i][i] = cost[i][i] = 0;
}
for( int i=1 ; i<=M ; i++ ){
scanf("%d%d%d%d",&a,&b,&c,&d);
if( c < map[a][b] ){ //重边长度不等的情况
map[a][b] = map[b][a] = c;
cost[a][b] = cost[b][a] = d;
} //重边相等长度的情况
else if( c==map[a][b] && d<cost[a][b] ){
cost[a][b] = cost[b][a] = d;
}
}
scanf("%d%d",&s,&t);
Dijstra(map,N,s,t);
}
return 0;
}
void Dijstra( int map[][MAX] , int N , int s , int t ){
//算法思路:最短路径递增,只适用于非负权边
int min , k , last=s;
memset( mark , 0 , sizeof( mark ) );
for( int i=1 ; i<=N ; i++ ){
dis[i] = map[s][i];
value[i] = cost[s][i];
}
mark[s] = 1; //源点标记
while( 1 ){
for( int i=1 , min=INF ; i<=N ; i++ ){ //寻找下一个dis最短的点
if( mark[i]==0 && dis[i]<min ){
min = dis[k=i];
}
}
mark[k] = 1; //标记dis最短的边
if( k==t ){
printf("%d %d\n",dis[t],value[t]);
return ;
}
for( int j=1 , min=INF ; j<=N ; j++ ){ //k点来松弛其他节点长度和花费
if( dis[k] + map[k][j] < dis[j] ){
dis[j] = dis[k] + map[k][j];
value[j] = value[k] + cost[k][j];
}
else if( dis[k]+map[k][j]==dis[j] && value[k]+cost[k][j]<value[j] ){
value[j] = value[k] + cost[k][j];
}
}
}
}
代码分析:采用了Dijstra算法(求单源点到其他点的最短路径),时间复杂度为O(n^2),分为三个步骤:寻找、标记、松弛。
Prim算法与Dijstra算法的区别:Prim是计算最小生成树的算法、Dijkstra是计算最短路径的算法;Prim算法的更新操作更新的cls是已访问集合到未访问集合中各点的距离;Dijkstra算法的更新操作更新的cls是源点到未访问集合中各点的距离,已经访问过的相当于已经找到源点到它的最短距离了;