[菜鸟高分求助]如何求得有向图中确定两点间所有不重复的路径

qpalwosk 2005-12-10 06:32:19
正在学习数据结构ing,遇到这个问题,书上没有现成答案,苦思良久不解,大家不吝赐教啊


如题,深度和广度遍历能找出第一条路径,如果还需要其他不重复的路径(至少有一个顶点异于第一条),应该如何实现?如果可能,如何一次性把所有可能的路径都找出来?

有没有可能第一次用最短路径算法找出两点间最短的,然后路径长度依次增加找出其他的可能的路径?


请各位大侠指点,随时关注,有答案了即时结贴给分,谢谢
...全文
597 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
qpalwosk 2005-12-12
  • 打赏
  • 举报
回复
搞了半天就多一条语句。。。。递归回来把used[j]清零就行了。。。。。。到后面也忘记看ShowLovE(天天)在前面的话了。。。。。惭愧
结贴啦 谢谢 boodweb(TTT) mmmcd(超超) ShowLovE(天天) 都是高手 佩服
mmmcd 2005-12-12
  • 打赏
  • 举报
回复
/*
假设图形如下,找A到D的所有路径
A--B
|\ |
| \|
C--D

0 1 1 1
1 0 0 1
1 0 0 1
1 1 1 0
*/

#include <iostream.h>
int g[4][4]={{0,1,1,1},{1,0,0,1},{1,0,0,1},{1,1,1,0}};
char path[4];
int used[4],pl;

void go(int i)
{
int j;
path[pl++]='A'+i;
if('A'+i=='D')
{
cout<<path[0];
for(j=1;j<pl;j++)
{
cout<<"->"<<path[j];
}
cout<<endl;
return;
}
for(j=0;j<4;j++)
{
if(g[i][j]==1 && used[j]==0)
{
used[j]=1;
go(j);
pl--;
used[j]=0;
}
}
}

int main()
{
used[0]=1;
go(0);
return 0;
}
qpalwosk 2005-12-11
  • 打赏
  • 举报
回复
我的意思和你完全一样 我所想的算法和你给出执行步骤也完全一致 我前面所问的问题只是问了一个具体的问题:在第10步的时候,用什么来判断D是可以参观的?
qpalwosk 2005-12-11
  • 打赏
  • 举报
回复
嗯 大概意思知道了 具体怎么实现还不太清楚 每个结点都多加一个数组成员的话 数组里面储存的是单个结点吧?但是需要考查的是某一条路径是否为其源头,就是说在D的数组里面A→B这条路径是怎么储存的,A→C呢,两者怎么区分开?
boodweb 2005-12-11
  • 打赏
  • 举报
回复
1. 实际上不会再次访问A->B了,遍历的时候肯定是根据相邻节点依次进行的,同一个相邻节点不会被访问两次
2. 历史信息其实就是路径,数组足矣,每次遍历新的节点就添加到数组末尾
boodweb 2005-12-11
  • 打赏
  • 举报
回复
唉,你还是没有明白我的意思,根本作什么不用比较,我把搜索详细过程跟你说了把
一共4个结点,ABCD,A为起点D为终点,存在两条路径,A→B→D A→C→D
前面是当前节点,后面是当前路径P
1. A, {}
2. A, {A}
3. B, {A}
4. B, {AB}
5. D, {AB}
6. D, {ABD}
这样得到第一条路径ABD
下面回溯
7. B, {AB}
8. A, {A}(B没有D以外的邻居了)
9. C, {A}(A还有邻居C)
10.C, {AC}
11.D, {AC}
12.D, {ACD}
这样得到了第二条路径ACD
算法中并没有将第一条第二条路径比较的过程,依次选择邻居的过程已经保证了两条路径的不同
qpalwosk 2005-12-11
  • 打赏
  • 举报
回复
大哥,大概原理是这样,但是当涉及到实现细节的时候一些原理要修正啊

我举那个只有5个结点的图可能是最简单的了,当结点增多的时候问题就没这么简单了,一个全局数组是不够用的

如果按照全局变量的方法,而不采用为每个结点设置数组记录其到访的祖先路径的方法,那么每一条走过的路都必须记录成一个单独的数组,比较的话必须按顺序比较数组中的所有元素,仅仅区分一个点或一部分点是不够的

比如刚才只有A→B→D和A→C→D两条路,如果再加一条路A→P→D的话,对于D点,就必须判断出A→B,A→C,A→P是三个不同的访问D的路径,并允许它们按顺序访问到D而不能禁止,那么需要的数组至少就有{A,B,D...} {A,C,D...} 当想从P访问D时,就查数组,发现A→P→D不在所有的历史数组中,如果我再在A和P之间插入一个Q点,A不但可以直接到P,还可以通过Q中转,那么A→P和A→Q→P都应该可以访问到D,这时加上前面A→B,A→C,一共4条到D的不同路线,至少需要3个数组加以区分,


而这个图还可以无限复杂下去,原则不变,只要有一个点不同就算不同的路径,我想问的就是怎么储存会更实用一点
boodweb 2005-12-11
  • 打赏
  • 举报
回复
干嘛非要把数组根节点关联起来呢?
数组作为全局变量好了
比如遍历到A->C的时候,应该是这样
path[0]={A,B,D,Z}
path[1]={A,C}
其中path[1]是当前路径,下一个节点D不在path[1]中,所以加入其中,变成
path[1]={A,C,D}
...

这些都是实现细节了,自己好好想想应该没问题
qpalwosk 2005-12-10
  • 打赏
  • 举报
回复
嗯,就是说对于每个结点,它自己要保存一个曾经访问过它的所有历史路径的信息,比如对于D,它先被A→B访问过,在第一次通过A→C访问时,通过查历史信息应该允许A→C可以到达D,如果通过再次通过A→B查历史信息就不应该允许其的访问

但是应该用什么存储结构来保存这个历史信息呢?(每个结点都应该有这个数据成员,而且要唯一的区分到达它的不同的路径)

boodweb 2005-12-10
  • 打赏
  • 举报
回复
哦,明白你的意思了
那也不难,继续遍历的条件变一下,本来是看到节点已经访问过就不访问了,现在改成只当节点存在于当前路径中时才不访问
比如你的例子:
A->B->D->Z,然后回溯到A->C,但是D不在当前路径中(即D不在{A,C}中),所以继续向前A->C->D->Z
不过此算法不会发现的路径中不会有圈
ShowLovE 2005-12-10
  • 打赏
  • 举报
回复
回溯后要清楚记录,就象这样:
used[i] = 1;
search( i + 1 );
used[i] = 0;
boodweb 2005-12-10
  • 打赏
  • 举报
回复
那就用BFS或者DFS继续遍历贝
qpalwosk 2005-12-10
  • 打赏
  • 举报
回复
对啊 遍历算法是完全不会走重复的任何一个点

而我需要的算法需要走重复的点,因为两条路径只需要有一个点不同就可以了

举个例子吧
一共5个结点,ABCDZ,A为起点Z为终点,存在两条路径,A→B→D→Z A→C→D→Z
DFS第一次找到路径A→B→D→Z后,只剩下C没有遍历到了,它就只会回溯到A,然后遍历到C,因为C后面的D已经遍历过了,所以算法到此终止

所以,我想问的就是,如何找到一条路径后,让后面的遍历可以重复遍历这条路径中的某些结点,但是又不能完全重复刚才的路径
boodweb 2005-12-10
  • 打赏
  • 举报
回复
ft,遍历算法本身就保证了不会再遍历到已经走过的路径
qpalwosk 2005-12-10
  • 打赏
  • 举报
回复
继续遍历找出结点的规则已经改变,并且很难判断

我在第一次遍历,会把找到的路径的结点记录下来,
但是后面继续遍历的话,因为只须要一个结点异于第一条路径即可,其他结点可任意重复,所以很难判断出第二次遍历时添加结点的规则

33,028

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧