最长路径问题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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值