给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 输入描述: 输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点t。输出最短距离及其花费 c语言
时间: 2023-12-16 08:04:21 浏览: 62
算法分析n个顶点e条边-数据结构——图
这道题可以使用 Dijkstra 算法来解决。每次从未被访问过的节点中选择距离起点最近的节点,并更新与该节点相邻的节点的距离和花费。在更新过程中,如果发现某个节点的最短距离相同,则选择花费更小的路径。
以下是代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAXN 1005
int n, m, s, t;
int dist[MAXN], cost[MAXN], vis[MAXN];
int edges[MAXN][MAXN][2]; // 存储边的长度和花费
void dijkstra() {
// 初始化
for (int i = 1; i <= n; i++) {
dist[i] = INT_MAX;
cost[i] = INT_MAX;
vis[i] = 0;
}
dist[s] = 0;
cost[s] = 0;
for (int i = 1; i <= n; i++) {
// 找到距离起点最近的未访问节点
int min_dist = INT_MAX, u = -1;
for (int j = 1; j <= n; j++) {
if (!vis[j] && dist[j] < min_dist) {
min_dist = dist[j];
u = j;
}
}
if (u == -1) break; // 找不到未访问节点,退出循环
vis[u] = 1;
// 更新与该节点相邻的节点的距离和花费
for (int v = 1; v <= n; v++) {
if (!vis[v] && edges[u][v][0] != -1) { // 存在边
if (dist[u] + edges[u][v][0] < dist[v]) { // 更新最短距离
dist[v] = dist[u] + edges[u][v][0];
cost[v] = cost[u] + edges[u][v][1];
} else if (dist[u] + edges[u][v][0] == dist[v]) { // 距离相等,选择花费更少的路径
if (cost[u] + edges[u][v][1] < cost[v]) {
cost[v] = cost[u] + edges[u][v][1];
}
}
}
}
}
}
int main() {
scanf("%d%d", &n, &m);
// 初始化边
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
edges[i][j][0] = edges[i][j][1] = -1;
}
}
// 读入边
for (int i = 1; i <= m; i++) {
int a, b, d, p;
scanf("%d%d%d%d", &a, &b, &d, &p);
edges[a][b][0] = edges[b][a][0] = d;
edges[a][b][1] = edges[b][a][1] = p;
}
scanf("%d%d", &s, &t);
dijkstra();
printf("%d %d\n", dist[t], cost[t]);
return 0;
}
```
阅读全文