怎么找出有向图中指定顶点间的 “所有” 路径
如何找出有向图中指定顶点间的 “所有” 路径。
如何找出有向图中指定顶点间的 “所有” 路径。
比如有如下有向图:
A->B->C->E
| ^
| |
-->D--
打印上图A到E的路径为:
A->B->C->E
A->B->D->E
请大家指点,谢谢了!
------解决方案--------------------
1)先用邻接矩阵A表示这个有向图如下:
1 1 0 0 0
0 1 1 0 0
0 0 0 1 1
0 0 0 0 1
0 0 0 0 1
2) 通过Warshall算法或者计算 矩阵A的一次方、二次方...五次方的或 得出 邻接矩阵 P如下:
1 1 1 1 1
0 1 1 1 1
0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
3)搜索A到E的路线,可以在这个矩阵里遍历,不难
------解决方案--------------------
如果有向图中没有环,或者要求路径中不能有重复节点,则推荐用DFS,保存每个节点的状态,进入节点与退出节点时修改状态即可;如果允许回路,一般说来会要求在N步之内到达目的地(否则就有无限条路径了),这个时候适合用BFS,可以用一个队列维护遍历过程。
个人不建议用矩阵运算,一是因为复杂度高,有冗余;二是因为难以处理回路,矩阵一般用来统计两点之间的路径总数,如果要列出所有路径的话会比较麻烦
------解决方案--------------------
迷宫老鼠问题中用到的递归回溯方法改动一下。
原问题是达到终点就退出,改为到达终点也要回溯。
代码稍后给出。
------解决方案--------------------
int maze[][];
typedef struct
{
int xoffset;//向左移动的单位
int yoffset;//向右移动的单位
}move_unit_t;
typedef struct
{
int x;
int y;
}Pos;
//迷宫周围隔上挡板
void block_maze()
{
int i;
for(i=0; i<MAZESIZE+2; i++)
{
maze[0][i]=1;
}
for(i=0; i<MAZESIZE+2; i++)
{
maze[MAZESIZE+1][i]=1;
}
for(i=0; i<MAZESIZE+2; i++)
{
maze[i][0]=1;
}
for(i=0; i<MAZESIZE+2; i++)
{
maze[i][MAZESIZE+1]=1;
}
}
//检测从src-->dest是否是连通的
int findpath(Pos& src,Pos& dest)
{
block_maze();
stack<Pos> S;
S.push(src);
//当前位置
Pos curpos;
curpos.x=-1;
curpos.y=-1;
//移动方向
move_unit_t move_unit[4];
//向东
move_unit[0].xoffset=0;
move_unit[0].yoffset=1;
//北
move_unit[1].xoffset=-1;
move_unit[1].yoffset=0;
//西
move_unit[2].xoffset=0;
move_unit[2].yoffset=-1;
//南
move_unit[3].xoffset=1;
move_unit[3].yoffset=0;
curpos=S.top();
while(!S.empty() )
{
if((curpos.x == dest.x) && (curpos.y == dest.y))
{
//达到终点,先打印路径,再进行回溯。
S.pop();
if(S.empty())
{
printf("\n%s,%s,%d,stack empty\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
curpos=S.top();
}
int i;
for(i=0; i<4; i++)
{
int x=curpos.x+move_unit[i].xoffset;
int y=curpos.y+move_unit[i].yoffset;
if(1 != maze[x][y])
{
//可以移动
maze[x][y]=1;
curpos.x=x;
curpos.y=y;
S.push(curpos);
break;
}
}
if(4==i)
{
//无路可进,需要回溯。
S.pop();
if(S.empty())
{
printf("\n%s,%s,%d,stack empty\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
curpos=S.top();
}
}
return 0;
}
如何找出有向图中指定顶点间的 “所有” 路径。
比如有如下有向图:
A->B->C->E
| ^
| |
-->D--
打印上图A到E的路径为:
A->B->C->E
A->B->D->E
请大家指点,谢谢了!
------解决方案--------------------
1)先用邻接矩阵A表示这个有向图如下:
1 1 0 0 0
0 1 1 0 0
0 0 0 1 1
0 0 0 0 1
0 0 0 0 1
2) 通过Warshall算法或者计算 矩阵A的一次方、二次方...五次方的或 得出 邻接矩阵 P如下:
1 1 1 1 1
0 1 1 1 1
0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
3)搜索A到E的路线,可以在这个矩阵里遍历,不难
------解决方案--------------------
如果有向图中没有环,或者要求路径中不能有重复节点,则推荐用DFS,保存每个节点的状态,进入节点与退出节点时修改状态即可;如果允许回路,一般说来会要求在N步之内到达目的地(否则就有无限条路径了),这个时候适合用BFS,可以用一个队列维护遍历过程。
个人不建议用矩阵运算,一是因为复杂度高,有冗余;二是因为难以处理回路,矩阵一般用来统计两点之间的路径总数,如果要列出所有路径的话会比较麻烦
------解决方案--------------------
迷宫老鼠问题中用到的递归回溯方法改动一下。
原问题是达到终点就退出,改为到达终点也要回溯。
代码稍后给出。
------解决方案--------------------
int maze[][];
typedef struct
{
int xoffset;//向左移动的单位
int yoffset;//向右移动的单位
}move_unit_t;
typedef struct
{
int x;
int y;
}Pos;
//迷宫周围隔上挡板
void block_maze()
{
int i;
for(i=0; i<MAZESIZE+2; i++)
{
maze[0][i]=1;
}
for(i=0; i<MAZESIZE+2; i++)
{
maze[MAZESIZE+1][i]=1;
}
for(i=0; i<MAZESIZE+2; i++)
{
maze[i][0]=1;
}
for(i=0; i<MAZESIZE+2; i++)
{
maze[i][MAZESIZE+1]=1;
}
}
//检测从src-->dest是否是连通的
int findpath(Pos& src,Pos& dest)
{
block_maze();
stack<Pos> S;
S.push(src);
//当前位置
Pos curpos;
curpos.x=-1;
curpos.y=-1;
//移动方向
move_unit_t move_unit[4];
//向东
move_unit[0].xoffset=0;
move_unit[0].yoffset=1;
//北
move_unit[1].xoffset=-1;
move_unit[1].yoffset=0;
//西
move_unit[2].xoffset=0;
move_unit[2].yoffset=-1;
//南
move_unit[3].xoffset=1;
move_unit[3].yoffset=0;
curpos=S.top();
while(!S.empty() )
{
if((curpos.x == dest.x) && (curpos.y == dest.y))
{
//达到终点,先打印路径,再进行回溯。
S.pop();
if(S.empty())
{
printf("\n%s,%s,%d,stack empty\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
curpos=S.top();
}
int i;
for(i=0; i<4; i++)
{
int x=curpos.x+move_unit[i].xoffset;
int y=curpos.y+move_unit[i].yoffset;
if(1 != maze[x][y])
{
//可以移动
maze[x][y]=1;
curpos.x=x;
curpos.y=y;
S.push(curpos);
break;
}
}
if(4==i)
{
//无路可进,需要回溯。
S.pop();
if(S.empty())
{
printf("\n%s,%s,%d,stack empty\n",__FILE__,__FUNCTION__,__LINE__);
break;
}
curpos=S.top();
}
}
return 0;
}