考虑到多个城市之间的路线图,两个城市之间的道路包含隧道,您的目标是找到起始城市和所有其他城市之间的最短路径,这样每条路径至少包含一条隧道。 (问题并不总是有解决方案)。假设道路的成本是给定的。输入 - 从文件输出到文件,包含起始城市和其他城市的路径。
现在我尝试用Dijkstra算法做到这一点,它解决了我的大部分问题,除了隧道是强制性的部分。谁能帮我这个?这是我的代码。 提前谢谢!
文件输入:
#include <stdio.h>
#define GRAPHSIZE 2048
#define INFINITY GRAPHSIZE*GRAPHSIZE
#define MAX(a, b) ((a > b) ? (a) : (b))
int e; /* The number of nonzero edges in the graph */
int n; /* The number of nodes in the graph */
long dist[GRAPHSIZE][GRAPHSIZE];/* dist[i][j] is the distance between node i and j; or 0 if there is no direct connection */
long d[GRAPHSIZE]; /* d[i] is the length of the shortest path between the source (s) and node i */
int prev[GRAPHSIZE]; /* prev[i] is the node that comes right before i in the shortest path from the source to i*/
void printD() {
int i;
printf("Distances:\n");
for (i = 1; i <= n; ++i)
printf("%10d", i);
printf("\n");
for (i = 1; i <= n; ++i) {
printf("%10ld", d[i]);
}
printf("\n");
}
/*
* Prints the shortest path from the source to dest.
* dijkstra(int) MUST be run at least once BEFORE
* this is called
*/
void printPath(int dest) {
if (prev[dest] != -1)
printPath(prev[dest]);
printf("%d ", dest);
}
void dijkstra(int s) {
int i, k, mini;
int visited[GRAPHSIZE];
for (i = 1; i <= n; ++i) {
d[i] = INFINITY;
prev[i] = -1; /* no path has yet been found to i */
visited[i] = 0; /* the i-th element has not yet been visited */
}
d[s] = 0;
for (k = 1; k <= n; ++k) {
mini = -1;
for (i = 1; i <= n; ++i)
if (!visited[i] && ((mini == -1) || (d[i] < d[mini])))
mini = i;
visited[mini] = 1;
for (i = 1; i <= n; ++i)
if (dist[mini][i])
if (d[mini] + dist[mini][i] < d[i]) {
d[i] = d[mini] + dist[mini][i];
prev[i] = mini;
}
}
}
int main(int argc, char *argv[]) {
int i, j;
int u, v, w;
FILE *fin = fopen("dist.txt", "r");
/* the first line contains e, the number of edges the following e lines
contain 3 numbers: u, v and w signifying that there’s an edge from u to v of weight w*/
fscanf(fin, "%d", &e);
for (i = 0; i < e; ++i)
for (j = 0; j < e; ++j)
dist[i][j] = 0;
n = -1;
for (i = 0; i < e; ++i) {
fscanf(fin, "%d%d%d", &u, &v, &w);
dist[u][v] = w;
n = MAX(u, MAX(v, n));
}
fclose(fin);
dijkstra(1);
printD();
printf("\n");
for (i = 1; i <= n; ++i) {
printf("Path to %d: ", i);
printPath(i);
printf("\n");
}
return 0;
}
答案 0 :(得分:1)
运行Dijkstra的算法,找到从起始城市到所有隧道的所有最短路径。
再次运行Dijkstra算法,以所有隧道为起点,找到通往所有其他城市的所有最短路径。因此,您将在Dijkstra算法的中间开始,您已经在priority queue中拥有一堆候选人(所有隧道),并且所有这些都将标记为已访问。
看起来你并没有使用优先级队列(Dijkstra算法的高效实现使用了一个),但我确信你会设法弄清楚如何将我的解决方案应用到你的代码中。 / p>
答案 1 :(得分:0)
您可以构建如下图形:每个城市有两个节点(对于每个城市C,请说C和C')。对于每条道路,例如从C1到C2,向图形添加边缘:C1-> C2和C1' - > C2'。对于每个隧道,例如从C1到C2,将边添加到图C1-> C2'和C1' - > C2'。
直觉是要到达C'节点,你必须通过至少一个隧道。
现在,要使用至少一个隧道找到从C1到C2的最短路径,只需使用Dijkstra找到从C1到C2'的最短路径。或者找到每个城市的最短路径,找到从每个城市C的起始城市到C'的所有最短路径。