社区
C语言
帖子详情
在不包含循环的有向图中,如何求得两个指定点间的最长路径?
Zark
2003-06-10 12:29:04
在不包含循环的有向图中,如何求得两个指定点间的最长路径? 请或给出伪码,或是C/C++/JAVA代码.既使是大致思路也可以.
预致谢意!
...全文
471
15
打赏
收藏
在不包含循环的有向图中,如何求得两个指定点间的最长路径?
在不包含循环的有向图中,如何求得两个指定点间的最长路径? 请或给出伪码,或是C/C++/JAVA代码.既使是大致思路也可以. 预致谢意!
复制链接
扫一扫
分享
转发到动态
举报
AI
作业
写回复
配置赞助广告
用AI写文章
15 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
Zark
2003-06-12
打赏
举报
回复
非常感谢,未能及时回话是因为昨天太忙,然后又要读你的代码,又要研究另一种算法,所以回复迟了.关于你的修改,我再看看,我在运行运程中没有遇到你所说的问题.我想可能是因为我的问题实际上不是任两点的路径,而是在图中只有一个入度为零的顶点和一个出度为零的顶点,我实际是在求这个两点的路径.我在考虑"关键路径"法,好像用拓扑有序这种方法也能解决,不过好像也是O(n^2).
孩皮妞野
2003-06-12
打赏
举报
回复
Zark, 怎么一直没回话,这里有个小bug, 可是我用完了3次,不能再发贴,把我急得。
unsigned max_path_length(unsigned i, unsigned j)
{
if(i==j) return 0; // 递归退出条件
if( max_paths[i][j] != unknown)
return max_paths[i][j]; //已经计算,直接取用计算结果
unsigned max_path = nopath;
unsigned next_vert; // 下一个节点
for(unsigned k=0; k<max_paths.size(); ++k){
if( adj_matrix[i][k]==1 ){ // k是i的后继
unsigned len = max_path_length(k,j);
// 这里做了局部修改,否则可能出现错误
// 当max_path不为nopath而len为nopath时会出现不合理的赋值动作。
if( len!=nopath && (max_path==nopath || max_path<len ) )
max_path = len, next_vert=k;
}
}
if(max_path != nopath)
++max_path;
max_paths[i][j]= max_path;
max_path_next_vert[i][j] = next_vert;
return max_path;
}
Zark
2003-06-12
打赏
举报
回复
非常感谢!经验证,结果正确。
孩皮妞野
2003-06-11
打赏
举报
回复
Zark(金陵五月) ( ) ,
是动态规划法,复杂度好像是O(n^2), 我想不会达不到你的精度要求吧。
建议看一下动态规划法的介绍。 如果有时间我会把这个题目写出来。算法出来了编程没有什么难度。
Zark
2003-06-11
打赏
举报
回复
如果我没有理解错的,你的算法实际上是从结点A到结点C进行多次搜索,并把每次搜索的路径都记录下来,比如A->B->C, A->D->B->C,然后再从其中选择最长的一组.
这是我最原始的想法,类似于穷举法.但我仿佛觉得应该还有更好的算法,不必进行穷举.众所周知,如果求A到C的最短路径,那么穷举法是完全可以成功的,但不是最好的,可以通过类似于树的广度搜索的方法,对A查B和D,发觉没有到达C,分别从B和D出度搜索C,结果是B可以到达C,那么这条路一定是最短的,这样不用穷举即可得到最短路径.
不知老兄对此有无高见,敬请赐教.
nKannan
2003-06-11
打赏
举报
回复
图的遍历问题。
使用一个队列,开始只有点A。
将A可以到达的点放入队列,BD。
查下一个点B,将B可以到达的点入队列,现在有DC。
反复查队列,直到为空。
记录其中到达C点所经历的最长路径。
这是实现最简单但是效率差的方法。
孩皮妞野
2003-06-11
打赏
举报
回复
记顶点数为N, 用一个N*N的矩阵来存储从每一顶点到所有其他顶点的最大长度。
这个矩阵可以一次求出来,反复使用,只要基础图没有改变。
如有问题,欢迎讨论。
孩皮妞野
2003-06-11
打赏
举报
回复
这是DP算法,是多项式复杂度吧。
孩皮妞野
2003-06-11
打赏
举报
回复
我刚才理解错了。
把边的权都置为1。
记从S到D的最长路径的长度为MAXsd,
从S可以直接到达的节点集合为{A,B,C,D...}
则MAXsd = 1+ max{ MAXad, MAXbd, MAXcd, MAXdd...}
在求最长路径长度的同时可以求出最长路径。
Zark
2003-06-11
打赏
举报
回复
多谢回复.
1.我的书上没有这种算法,如有可能请告诉我是哪一本书.
2.这个图没有那么复杂,边是没有权的.举例来说,
A----->B----->C
| ^|
---->D---
从A->C,则要找出A->D->B->C,而不是A->B->C.我不知道如何使用ALNG的方法.
孩皮妞野
2003-06-11
打赏
举报
回复
哦,是图,可以用最小代价生成树的算法[prim/kruskal]. 道理如上。
孩皮妞野
2003-06-11
打赏
举报
回复
你是指不包含同一节点两次的最长路径吧?
最长和最短,看你怎么看。比如对边的权取相反数,或者用某个大数减去权得到新权[这样可以保证权仍为正数],这样用新权得到的最短路径,就是原来权意义上的最长路径。
所以dijikstra算法就可以了。
brucegong
2003-06-11
打赏
举报
回复
数据结构上不是有现成的算法吗?
孩皮妞野
2003-06-11
打赏
举报
回复
另一组稍复杂的数据
C:\ type input.txt
0 9
13
0 1 0 1 0 0 0 0 0 0 0 0 0
0 0 1 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0
0 1 0 0 1 0 0 0 0 0 0 0 0
0 0 1 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1 0 1 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 1 0 0 1
0 0 0 0 0 0 0 0 0 1 0 0 0
c:\ lpath <input.txt
11
0 3 1 4 2 5 6 8 10 11 12 9
这个结果也是正确的。
该算法的复杂度为O(n^2).
孩皮妞野
2003-06-11
打赏
举报
回复
局部还可以优化。在CB6下运行通过,以你的样本数据测试通过。没做进一步测试。
必须保证输入的矩阵没有回路,否则可能陷入死循环[?]。
// 解Zark最长路径问题的DP算法。
// ALNG 2003-6-11
//
//
//---------------------------------------------------------------------------
// 输入文件的格式
// 源 目标
// 顶点数
// 邻接矩阵
//
// 示例输入文件input.txt, 就是zark给出的示例图
// 0 2
// 4
// 0 1 0 1
// 0 0 1 0
// 0 0 0 0
// 0 1 0 0
//
// 输出
// 路径长度
// 路径
//
// 示例输出
// 3
// 0 3 2
#include <iostream>
#include <vector>
typedef std::vector< std::vector<unsigned> > matrix;
matrix max_paths; // 存储最长路径长度的矩阵
matrix max_path_next_vert; // 用于构造出最长路径
matrix adj_matrix; // 邻接矩阵
// max_paths中用到的特殊值
const unsigned unknown = 0, // 表明两个顶点间的最长路径长度未知
nopath = unsigned(-1); // 表明两个顶点间的最长路径长度未知
// 从标准输入中读入邻接矩阵
//
// input:
// n[in]: count of vertices
//
// remark: this function modifies global variable max_paths and adj_matrix
void read_adj_matrix(unsigned n)
{
// read adjacent matrix from stand input
adj_matrix.resize(n);
for(unsigned i=0; i<n; ++i){
adj_matrix[i].resize(n);
for(unsigned j=0; j<n; ++j){
std::cin>>adj_matrix[i][j];
}
}
// initialize max_paths, set all of its elements to unknown
max_paths.resize(n);
max_path_next_vert.resize(n);
for(unsigned i=0; i<n; ++i){
max_paths[i].resize(n);
max_path_next_vert[i].resize(n);
for(unsigned j=0; j<n; ++j)
max_paths[i][j] = unknown;
}
}
// 取得从i到j的最大路径的长度
//
// 返回 unsigned(-1)表示没有从i到j的路径
// 其它:
unsigned max_path_length(unsigned i, unsigned j)
{
if(i==j) return 0; // 递归退出条件
if( max_paths[i][j] != unknown)
return max_paths[i][j]; //已经计算,直接取用计算结果
unsigned max_path = nopath;
unsigned next_vert; // 下一个节点
for(unsigned k=0; k<max_paths.size(); ++k){
if( adj_matrix[i][k]==1 ){ // k是i的后继
unsigned len = max_path_length(k,j);
if( max_path==nopath || max_path<len )
max_path = len, next_vert=k;
}
}
if(max_path != nopath)
++max_path;
max_paths[i][j]= max_path;
max_path_next_vert[i][j] = next_vert;
return max_path;
}
void longest_path(unsigned i, unsigned j)
{
unsigned len;
if( (len=max_path_length(i,j) ) != nopath){
std::cout<<len<<std::endl<<i;
for(unsigned k=max_path_next_vert[i][j]; k!=j;i=k,k=max_path_next_vert[i][j])
std::cout<<' '<<k;
std::cout<<' '<<j<<std::endl;
}else
std::cout<<"there is no path between "<<i<<" and "<<j<<std::endl;
}
#pragma argsused
int main(int argc, char* argv[])
{
using std::cin;
using std::cout;
using std::endl;
unsigned src, dst, n;
cin>>src>>dst>>n;
read_adj_matrix(n);
longest_path(src,dst);
return 0;
}
//---------------------------------------------------------------------------
说出你们的故事—网络沟通-新娘篇.docx
说出你们的故事—网络沟通-新娘篇.docx
网络营销全案框架协议.doc
网络营销全案框架协议.doc
独立游戏开发的崛起和机遇.pptx
独立游戏开发的崛起和机遇.pptx
光纤综合布线方案设计.docx
光纤综合布线方案设计.docx
蓝紫渐变简约IOS风PPT模板.pptx
蓝紫渐变简约IOS风PPT模板.pptx
C语言
70,022
社区成员
243,263
社区内容
发帖
与我相关
我的任务
C语言
C语言相关问题讨论
复制链接
扫一扫
分享
社区描述
C语言相关问题讨论
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章