在循环图中寻找最长路径存在哪些优化?
循环图中的最长路径已知是NP-完全的.什么样的优化或启发式可以使查找最长路径的速度比整个图的DFSing快?有什么概率方法吗?
我有一个具有特定性质的图表,但我正在寻找一般情况下的答案。链接到文件就太棒了。以下是部分答案:
发布于 2010-11-24 06:58:10
下面是一个O(n*2^n)动态规划方法,对于20个顶点来说应该是可行的:
m(b, U)
=以b
结尾的任何路径的最大长度,并且只访问U
中的(某些)顶点。
最初,设置m(b, {b}) = 0
。
然后,m(b, U)
= m(x, U - x) + d(x, b)
在U
中所有x
上的最大值,使得x
不是b
,并且存在边缘(x, b)
。对于所有端点b
,取这些值的最大值,使用U
= V
(完整的顶点集)。这将是任何路径的最大长度。
下面的C代码在d[N][N]
中假定一个距离矩阵。如果图未加权,则可以将对此数组的每次读取访问更改为常量1
。还在阵列p[N][NBITS]
中计算显示最佳顶点序列(可能有多个顶点)的回溯。
#define N 20
#define NBITS (1 << N)
int d[N][N]; /* Assumed to be populated earlier. -1 means "no edge". */
int m[N][NBITS]; /* DP matrix. -2 means "unknown". */
int p[N][NBITS]; /* DP predecessor traceback matrix. */
/* Maximum distance for a path ending at vertex b, visiting only
vertices in visited. */
int subsolve(int b, unsigned visited) {
if (visited == (1 << b)) {
/* A single vertex */
p[b][visited] = -1;
return 0;
}
if (m[b][visited] == -2) {
/* Haven't solved this subproblem yet */
int best = -1, bestPred = -1;
unsigned i;
for (i = 0; i < N; ++i) {
if (i != b && ((visited >> i) & 1) && d[i][b] != -1) {
int x = subsolve(i, visited & ~(1 << b));
if (x != -1) {
x += d[i][b];
if (x > best) {
best = x;
bestPred = i;
}
}
}
}
m[b][visited] = best;
p[b][visited] = bestPred;
}
return m[b][visited];
}
/* Maximum path length for d[][].
n must be <= N.
*last will contain the last vertex in the path; use p[][] to trace back. */
int solve(int n, int *last) {
int b, i;
int best = -1;
/* Need to blank the DP and predecessor matrices */
for (b = 0; b < N; ++b) {
for (i = 0; i < NBITS; ++i) {
m[b][i] = -2;
p[b][i] = -2;
}
}
for (b = 0; b < n; ++b) {
int x = subsolve(b, (1 << n) - 1);
if (x > best) {
best = x;
*last = b;
}
}
return best;
}
在我的PC上,这解决了一个20x20完全图的边权随机选择在范围[0,1000)在大约7s和需要约160 my (其中一半是为前任跟踪)。
(请不要评论使用固定大小的数组.)在实际程序中使用malloc()
(或者更好的是C++ vector<int>
)。我就是这样写的,这样事情就更清楚了。)
https://stackoverflow.com/questions/4252215
复制相似问题