需要算法的帮助来找到DAG中的最大路径
Need assistance with algorithm to find the maximum path in a DAG
假设我有一个有向非循环图(DAG),其中有一条从每个节点(底部行中的节点除外)到下面两个节点的有向边:
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
我需要找到一条通过DAG的路径,其中节点的权重之和最大化。只能从此树中的节点向左或向右对角移动。例如,7,3,8,7,5将给出该树中的最大路径。
输入文件包含以这种方式格式化的DAG
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
我的问题是,找到最大路径的最佳算法是什么?这个树在C++中如何表示?
节点权重为非负。
我用int
s的向量表示这个三角形。
从最下面一行开始,比较每对相邻的数字。取较大的一个,将其添加到该对上方的数字:
5 3 13 3
7 8 6 becomes 7 8 6
^ ^
13 3 13 11
/
Next iteration 7 8 6 becomes 7 8 6 etc.
^ ^
按照你的方式到达顶点,当你完成时,三角形的尖端将包含最大的和。
二维数组可以正常工作。您可以通过使用广度优先遍历来实现这一点,并用该节点的最大路径和标记每个访问节点。
例如:
- 只有从7开始才能达到7
- 3用10表示,8用15表示
- 8标记为18(10+8),1标记为11,然后替换为16,0标记为15
标记叶节点后,快速浏览它们,看看哪个节点最大。然后,通过比较当前节点的权重、父节点的权重和边权重来开始回溯。
扰流板
如果您想自己解决这个问题,请不要阅读代码
解决这个问题的一种方法是将数据转化为一棵树(实际上是图),并编写一个递归算法,通过将树缩减为较小的子树(直到你有一棵只有一个节点的树)来找到通过树的最大路径,然后从那里开始向上。
我真的很喜欢递归算法和使用树,所以我写了一个程序来做这件事:
#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
struct node {
node(int i, node* left = NULL, node* right = NULL) : data(i), left(left), right(right) { }
node* left, *right;
int data;
};
/*
tree:
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
*/
std::vector<node*> maxpath(node* tree, int& sum) {
if (!tree) {
sum = -1;
return std::vector<node*>();
}
std::vector<node*> path;
path.push_back(tree);
if (!tree->left && !tree->right) {
sum = tree->data;
return path;
}
int leftsum = 0, rightsum = 0;
auto leftpath = maxpath(tree->left, leftsum);
auto rightpath = maxpath(tree->right, rightsum);
if (leftsum != -1 && leftsum > rightsum) {
sum = leftsum + tree->data;
copy(begin(leftpath), end(leftpath), back_inserter<vector<node*>>(path));
return path;
}
sum = rightsum + tree->data;
copy(begin(rightpath), end(rightpath), back_inserter<vector<node*>>(path));
return path;
}
int main()
{
// create the binary tree
// yay for binary trees on the stack
node b5[] = { node(4), node(5), node(2), node(6), node(5) };
node b4[] = { node(2, &b5[0], &b5[1]), node(7, &b5[1], &b5[2]), node(4, &b5[2], &b5[3]), node(4, &b5[3], &b5[4]) };
node b3[] = { node(8, &b4[0], &b4[1]), node(1, &b4[1], &b4[2]), node(0, &b4[2], &b4[3]) };
node b2[] = { node(3, &b3[0], &b3[1]), node(8, &b3[1], &b3[2]) };
node n(7, &b2[0], &b2[1]);
int sum = 0;
auto mpath = maxpath(&n, sum);
for (int i = 0; i < mpath.size(); ++i) {
cout << mpath[i]->data;
if (i != mpath.size() - 1)
cout << " -> ";
}
cout << endl << "path added up to " << sum << endl;
}
它打印
7->3->8->7->5
路径总计30
最好的算法是
open the file,
set a counter to 0.
read each line in the file.
for every line you read,
increment the counter.
close the file.
that counter is your answer.
表示树的最佳算法将是零。因为你实际上并没有做任何需要树重新呈现的事情。