最长路径问题dp

看了Geek_ling的博文后写的代码,原先也写过最长路径问题(uva10000),不过用的是spfa算法

具体的讲解戳 http://www.cnblogs.com/yanlingyin/archive/2011/11/12/2246716.html

求子问题之前先进行拓扑排序,然后根据状态方程 :dilg(v)=max(u,v)∈E{dilg(u)+w(u, v)}; dilg(v)表示从源点 到 v 点的最长路径长度。还是比较容易理解的。

#include <iostream>
using namespace std;

const int maxn = 100;
int map[maxn][maxn];
int pre[maxn];//入度
bool has[maxn];//是否排序
int order[maxn];//拓扑序列

int edge_num;//边的数量
int node_num;

int dp[maxn];//dp[i] 从源节点 到i节点的 最长路径长度
int parent[maxn];//节点i的前驱节点

void init()
{
	int one,two,weight;
	memset(pre,0,sizeof(pre));
	memset(map,0,sizeof(map));

	for(int i = 0;i < edge_num;i++)
	{
		cin>>one>>two>>weight;
		map[one][two] = weight;
		pre[two]++;
	}
	memset(has,false,sizeof(has));
	memset(dp,-1,sizeof(dp));

}


void topo(int dep)//首次调用时dep = 1 order[1---node_num]
{
	for(int i = 1;i < maxn && dep <= node_num;i++)
	{
		if(!has[i] && pre[i]==0)
		{
			has[i] = true;
			order[dep] = i;
			for(int k = 1;k < maxn;k++)
			{
				if(map[i][k] != 0)
					pre[k]--;
			}
			dep++;
			i = 0;//每次从开头开始遍历 这部分处理的不好,因为后面的数字 会判断为一个个的 独立 结点
			if(dep > node_num)
				break;
		}
	}
}

void solve()
{
	memset(parent,0,sizeof(parent));
	memset(dp,0,sizeof(dp));

	for(int i = 1;i <= node_num;i++)//自底向上求解子问题
	{
		for(int j = 1;j < maxn;j++)
		{
			if(map[j][order[i]])
			{
				if(dp[order[i]] < dp[j] + map[j][order[i]])
				{
					dp[order[i]] = dp[j] + map[j][order[i]];
					parent[order[i]] = j;
				}
			}
		}//for int j
	}//for int i
}

void print(int n)
{
	if(parent[n] != 0)
		print(parent[n]);
	cout<<n<<" ";
}

int main()
{
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
	int goal;
	while(cin>>node_num>>edge_num)
	{
		init();
		topo(1);
		solve();
		cin>>goal;
		print(goal);
		cout<<endl;
	}
	return 0;
}

测试数据:

6 8
6 1 1
6 3 2
3 1 4
1 2 6
3 4 3
2 4 1
2 5 2
4 5 1
5

输出:

6 3 1 2 5


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在一个有向无环中(DAG),求最长路径长度的问题可以使用拓扑排序和动态规划来解决。 具体步骤如下: 1. 对 DAG 进行拓扑排序,得到一个顶点的拓扑序列。 2. 初始化一个数组 dp,其中 dp[i] 表示以顶点 i 为终点的最长路径长度。 3. 遍历拓扑序列,对于每个顶点 i,遍历它的所有入边 (j, i),更新 dp[i] 为 max(dp[i], dp[j] + weight(j, i)),其中 weight(j, i) 表示从顶点 j 到顶点 i 的边权重。 4. 最终 dp 数组中的最大值即为最长路径长度。 Java 代码实现如下: ```java import java.util.*; public class LongestPath { public static int longestPath(List<List<Integer>> graph, int n) { int[] inDegree = new int[n]; // 入度数组 int[] dp = new int[n]; // 动态规划数组 // 计算入度数组 for (int i = 0; i < n; i++) { for (int j : graph.get(i)) { inDegree[j]++; } } // 执行拓扑排序 Queue<Integer> queue = new LinkedList<>(); for (int i = 0; i < n; i++) { if (inDegree[i] == 0) { queue.offer(i); } } while (!queue.isEmpty()) { int curr = queue.poll(); for (int next : graph.get(curr)) { inDegree[next]--; dp[next] = Math.max(dp[next], dp[curr] + 1); if (inDegree[next] == 0) { queue.offer(next); } } } // 找到最长路径长度 int maxPathLength = 0; for (int i = 0; i < n; i++) { maxPathLength = Math.max(maxPathLength, dp[i]); } return maxPathLength; } public static void main(String[] args) { List<List<Integer>> graph = new ArrayList<>(); graph.add(Arrays.asList(1, 2)); graph.add(Arrays.asList(3)); graph.add(Arrays.asList(3)); graph.add(Collections.emptyList()); int n = 4; System.out.println(longestPath(graph, n)); // 输出 2 } } ``` 在这个例子中,有向无环如下所示: ``` 0 -> 1 -> 3 \-> 2 -/ ``` 其中顶点 0 到顶点 3 的最长路径长度为 2。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值