一道最短路问题。普通最短路问题的边只有一种权值,而此题的边要考虑两种权值。因为节点n<=1000,所以不能够使用Floyd算法,时间复杂度较高,这里使用Dijkstra算法解决。
中文描述,题意不再赘述。只是要注意每条边都有距离和花费两种权,当且仅当两条边的距离相等时才比较花费。因为需要考虑两种权,所以算法代码要有相应的改变。另外,要考虑重边的问题,依旧要考虑两种权值。
下面是解题代码:Dijkstra解法
#include <stdio.h>
#define N 1001
#define INF 9999999
int map[N][N]; /*距离图*/
int cost[N][N]; /*花费图*/
int dis[N]; /*起点到i的距离*/
int cos[N]; /*起点到i的花费*/
int flag[N]; /*标志变量*/
int n, m;
int s, t;
void Init(); /*初始化*/
void Read(); /*输入*/
void Dijkstra();
int main()
{
while (~scanf("%d %d", &n, &m))
{
if (n == 0 && m == 0)
{
break;
}
Init();
Read();
Dijkstra();
printf("%d %d\n", dis[t], cos[t]);
}
return 0;
}
void Init() /*初始化*/
{
int i, j;
for (i=1; i<=n; ++i)
{
for (j=1; j<=n; ++j)
{
map[i][j] = cost[i][j] = INF;
}
dis[i] = cos[i] = INF;
flag[i] = 0;
}
return;
}
void Read() /*输入*/
{
int i;
int a, b, c, d;
for (i=0; i<m; ++i)
{
scanf("%d %d %d %d", &a, &b, &c, &d);
if (map[a][b] > c || (map[a][b] == c && cost[a][b] > d)) /*解决重边*/
{
map[a][b] = map[b][a] = c;
cost[a][b] = cost[b][a] = d;
}
}
scanf("%d %d", &s, &t);
return;
}
void Dijkstra()
{
int i, j, k;
int mind, minc;
dis[s] = cos[s] = 0;
for (i=1; i<=n; ++i)
{
mind = minc = INF;
for (j=1; j<=n; ++j)
{
/*多权值的比较*/
if (flag[j] == 0 && (mind > dis[j] || (mind == dis[j] && minc > cos[j])))
{
mind = dis[k = j];
minc = cos[k];
}
}
flag[k] = 1;
for (j=1; j<=n; ++j)
{
if (flag[j] == 0 && dis[j] > dis[k] + map[k][j])
{
dis[j] = dis[k] + map[k][j];
cos[j] = cos[k] + cost[k][j];
}
/*当距离相同时考虑花费*/
if (flag[j] == 0 && dis[j] == dis[k] + map[k][j] && cos[j] > cos[k] + cost[k][j])
{
cos[j] = cos[k] + cost[k][j];
}
}
}
return;
}