DAG最长路径求法

所谓DAG就是有向无环图,利用关键路径的做法有些复杂。
我们建立一个数组dp[n+1], dp[i]代表从这个结点出发的最长路径, 那么要求出dp[i], 我们只要求出从i出发的下一结点的dp[j], 使得dp[i] = max(dp[i], dp[j] + G[i][j]), 这就是它的状态转移方程.

可是dp[j] 怎么求呢? 同理,我们如果求出它的后一个结点的dp[k], 我们就可以相应求出dp[j].

经过上面的分析, 不难发现, 整个的过程可以用递归实现. 当i结点的出度为0时, 我们就可以给出dp[i] = 0, 从而实现整个问题的求解.
一、固定起点求最长路径

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int len=101;
struct g {
	int v;
	int w;
};
vector<g>G[len];
int dp[len];
bool visit[len];
int choice[len];//存路径
int DP(int i) {
	if(visit[i])
		return dp[i];
	visit[i]=true;
	for(int j=0; j < G[i].size(); j++) {
		if(dp[i]<DP(G[i][j].v)+G[i][j].w) {//逆拓扑求最长路径
			dp[i]=DP(G[i][j].v)+G[i][j].w;
			choice[i]=G[i][j].v;//存后继节点
		}
	}
	return dp[i];
}
void printPath(int i) {
	cout<<i;
	while(choice[i]!=-1) {
		cout<<"->"<<choice[i];
		i=choice[i];
	}
}
int main() {
	int n,m,start;
	cin>>n>>m>>start;
	fill(dp,dp+len,0);
	fill(visit,visit+len,false);
	fill(choice,choice+len,-1);
	for(int i = 0; i < m; i++) {
		int x,y,w;
		cin>>x>>y>>w;
		g t;
		t.v=y;
		t.w=w;
		G[x].push_back(t);
	}
	cout<<DP(start)<<endl;
	printPath(start);
	return 0;
}

在这里插入图片描述

二、国定终点求最长路径

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int len=101;
int Grap[len][len];
int dp[len];
bool visit[len];
int choice[len];//存路径
int n,m,end;
int DP(int i) {
	if(visit[i])
		return dp[i];
	visit[i]=true;
	for(int j=1; j <= n; j++) {
		if(Grap[j][i]!=-1) {
			if(dp[i]<DP(j)+Grap[j][i]) {
				dp[i]=DP(j)+Grap[j][i];
				choice[i]=j;
			}
		}
	}
	return dp[i];
}
void printPath(int i) {
	cout<<i;
	while(choice[i]!=-1) {
		cout<<"->"<<choice[i];
		i=choice[i];
	}
}
int main() {
	cin>>n>>m>>end;
	fill(dp,dp+len,0);
	fill(visit,visit+len,false);
	fill(choice,choice+len,-1);
	fill(Grap[0],Grap[0]+len*len,-1);
	for(int i = 0; i < m; i++) {
		int x,y,w;
		cin>>x>>y>>w;
		Grap[x][y]=w;
	}
	cout<<DP(end)<<endl;
	printPath(end);
	return 0;
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40394960/article/details/105900925
DAG
今日推荐