动态规划——有向加权图最长路径问题

有向加权图(DAG)最长路径问题

有向加权图最长路径问题是图论中一个重要的问题,可以通过动态规划的思想进行解决。

问题描述

给定一个有向加权无环图G,从G中找出无入度的顶点s,求从s出发到其他顶点的最长路径

动态规划——有向加权图最长路径问题_第1张图片

下文源代码运行结果参照此图

设计分析

首先,对于一般的图来说,求最长路径不像求最短路径那样简单,最长路径没有最优子结构。实际上,最长路径属于NP-hard问题。其次,图不能存在环路,如果图中存在有环路,我们可以很容易想到最长路径就变成无穷大了。因此,对于DAG来说,最长路径就存在解了。

如何利用动态规划解决该问题呢?

我们将上图进行一定的变形:
动态规划——有向加权图最长路径问题_第2张图片
此时我们就可以清楚地看出最长路径。

设: d i l g ( V ) dilg(V) dilg(V)表示以点V结尾的最长路径:
d i l g ( V ) = m a x ( u , v ) ∈ E ( d i l g ( u ) + w ( u , v ) ) dilg(V)=max_{(u,v)\in E}(dilg(u)+w(u,v)) dilg(V)=max(u,v)E(dilg(u)+w(u,v))
对于D点来说:
d i l g ( D ) = m a x ( d i l g ( B ) + 1 , d i l g ( C ) + 3 ) dilg(D)=max(dilg(B)+1,dilg(C)+3) dilg(D)=max(dilg(B)+1,dilg(C)+3)

这样求点D最长路径的问题就转化为求B、C最长路径的问题了。大问题被转化为小问题求解了;
当到达最小的问题时,即当只有两个点时,其中一个点是起点S时,最长路径就位起点到该点的距离,如 d i l g ( C ) = 2 dilg(C)=2 dilg(C)=2

源代码

#include 
#include 
using namespace std;

int solve(vector < vector<int> > &g, vector<int> &p, vector<int> &dilg, int i) {
	int n = g.size();
	if (dilg[i])
		return dilg[i];
	for (int j = 1; j < n; j++) {
		if (g[i][j] != INT_MAX && i != j) {
			if (dilg[i] < solve(g, p, dilg, j) + g[i][j]) { //比较入度的点的最长路径
				dilg[i] = solve(g, p, dilg, j) + g[i][j];
				p[i] = j;	//记录路径
			}
		}
	}
	return dilg[i];
}

void getPath(vector<int> &p, int i) {
	cout << "路径为:";
	int k = i;
	while (k) {
		cout << k << " ";
		k = p[k];
	}
	cout << endl;
}

void Dplongestpath(vector < vector<int> > &g) {
	int n = g.size();
	vector<int> path(n, 0);
	vector<int> dilg(n, 0);
	int i;
	for (i = 1; i < n; i++) {
		bool no_in = true;
		for (int j = 1; j < n; j++) {
			if (i == j)
				continue;
			if (g[j][i] != INT_MAX)
				no_in = false;
		}
		if (no_in)
			break;
	}
	

	cout << "最长路径为:" << solve(g, path, dilg, i) << endl;
	getPath(path, i);
}


int main() {
	int vexNum;
	cout << "输入顶点数量:";
	cin >> vexNum;
	vector < vector<int> >graph(vexNum + 1, vector<int>(vexNum + 1, INT_MAX));
	for (int i = 1; i < vexNum; i++)
		graph[i][i] = 0;
	cout << "输入邻接边信息:(顶点a 顶点b 权值w (输入0结束))" << endl;
	int a, b, w;
	while (cin >> a && a) {
		cin >> b >> w;
		graph[a][b] = w;
	}

	Dplongestpath(graph);//DAG最长路径

	system("pause");
	return 0;
}

运行结果

动态规划——有向加权图最长路径问题_第3张图片

你可能感兴趣的:(算法,#,动态规划,#,图论)