看了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