【发布时间】:2015-07-25 06:40:51
【问题描述】:
我有一个任务要做算法,它会在图中找到最长的路径。我将在输入上输入两个数字(N,M),这意味着矩阵的大小,以及N*M 数字。它们表示每个顶点的值。我必须找到从第一个顶点到最后一个顶点的最长路径,我只能向下或向右移动。所以输入例如:
4 5
1 2 5 1 2
3 2 1 2 1
1 4 3 2 1
3 1 2 2 2
输出是
19
最长的路径依次包括这些顶点:1,3,2,4,3,2,2,2
我使用了 Bellman-Ford 算法,因为我已将每个顶点的值更改为负数。但是这个算法对于大量的 vetices (1000x1000) 来说太慢了。是否有任何选项可以更改此算法以仅找到两个顶点(第一个和最后一个)之间的最大路径,而不是第一个和每个其他顶点之间的路径?这是我的代码:
# include <stdio.h>
# include <stdlib.h>
typedef struct {
int source;
int dest;
int weight;
} Edge;
void BellmanFord(Edge edges[], int edgecount, int nodecount, int source)
{
int *distance = malloc(nodecount * sizeof *distance);
int i, j;
distance[source] = -1;
for (i=0; i < nodecount; ++i) {
for (j=0; j < edgecount; ++j) {
if (distance[edges[j].source] < 0) {
int new_distance = distance[edges[j].source] + edges[j].weight;
if (new_distance < distance[edges[j].dest])
distance[edges[j].dest] = new_distance;
}
}
}
printf("%d\n",-distance[nodecount-1]-1);
free(distance);
return;
}
int main(void)
{
Edge *edges;
edges = malloc(2000000*sizeof(Edge));
int n,m,i,k,chodbapomoc,q = 0,p = 0,pamat;
scanf("%d %d",&n,&m);
for(i = 0; i < n*m;i++){ //this is transformation of input to edges
if(i != n*m-1) //list, so i can go only down or right
scanf("%d",&chodbapomoc);
if(p%m != m-1 && p != 0){
edges[q].source = p;
edges[q].dest = p+1;
edges[q++].weight = -chodbapomoc;
}
else if(i == 0){
k = chodbapomoc;
scanf("%d",&chodbapomoc);
edges[q].source = p;
edges[q].dest = p+1;
edges[q++].weight = -chodbapomoc-k;
}
if(p > m-1 && p != m){
edges[q].source = p-m;
edges[q].dest = p;
edges[q++].weight = -pamat;
}
else if(i == m-1){
edges[q].source = 0;
edges[q].dest = m;
edges[q++].weight = -chodbapomoc-k;
}
pamat = chodbapomoc;
p++;
}
BellmanFord(edges, q, n*m, 0);
return 0;
}
或者还有比这更快的其他选项来找到 DAG 中的最长路径吗? 而且,有什么方法可以记住最大路径中的哪些 verices?
感谢回复
【问题讨论】:
-
Floyd Warshall 处理节点之间的负距离
-
如何将输入转换为这条边,如果我可以向左移动,有什么可以改变的?