程序员面试金典: 9.4树与图 4.2给定有向图,设计一个算法,找出两个节点之间是否存在一条路径。

本文介绍了如何在给定的有向图中判断两个节点之间是否存在路径。通过使用广度优先搜索(BFS)进行图遍历,标记已访问节点,若能到达目标节点则说明存在路径,否则不存在。示例代码展示了具体实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <iostream>
#include <stdio.h>
#include <vector>
#include <queue>

using namespace std;

/*
问题:给定有向图,设计一个算法,找出两个节点之间是否存在一条路径。
分析:有向图,无非是没有顶点的树,需要考虑顶点和边。
      图的两种创建方式:邻接矩阵,邻接表。
	  找出两个节点之间是否存在一条路径。Dijstra:两点之间最短路径,Flord是任意两点最短路径。
	  还有连通图的最短路径。
	  图的遍历有:深度优先和广度优先。


输入:
5(结点个数,元素下标从1开始) 5(有向边个数)
1(起始结点编号) 5(结束结点编号)
1 2(有向边,从结点1指向节点2)
1 3
2 3
2 4
3 5

5 4
1 5
1 2 
1 3
2 3 
2 4 


输出:
exist path
not exist path

未能解出

关键:
1 迪杰斯特拉算法是求指定点到其他节点的单源最短路径(但必须是无向图),所以此题不能用dijkstra算法
2 只需要从两个节点中任意一个节点出发,继续遍历,访问过的节点标记为已经访问,即可。
  之所以没想到是因为:考虑图的遍历的时候想到如果是非连通图,认为就无法继续向下遍历了。就排除了图的遍历。
  实际上:图遍历过程中如果到一次遍历结束后,包含了另外一个节点,说明两者连通;否则,不连通。
  之所以考虑到dijkstra算法是因为想到求指定点到其他节点单元最短路径,但是没考虑到迪杰斯特拉算法需要无向图,
  否则,有向图连接中存在无法连通情况,单源最短路径不一定能求出。

3 记住遍历就两种:广度优先(队列+结构体) ,深度优先(递归)
*/
const int MAXSIZE = 1000;




typedef struct Node
{
	Node(int value):_value(value){}
	int _value;
};


//图的遍历
bool isTwoNodeInPath(int beginNode , int endNode , vector<Node> vecNode[MAXSIZE + 1])
{
	int g_visit[MAXSIZE];
	memset(g_visit , 0 , sizeof(int) * MAXSIZE);
	//设置所有节点为
	Node node(beginNode);
	g_visit[beginNode] = 1;
	queue<Node> queueNode;
	queueNode.push(node);
	while(!queueNode.empty())
	{
		//弹出当前节点
		Node curNode = queueNode.front();
		queueNode.pop();
		int value = curNode._value;
		int size = vecNode[value].size();
		//遍历所有连接的节点并压入到队列中
		for(int i = 0 ; i < size; i++)
		{
			Node tempNode = vecNode[value].at(i);
			//压入之前,如果该结点已经被访问,则不压入
			if(g_visit[tempNode._value] == 1)
			{
				continue;
			}
			g_visit[tempNode._value] = 1;
			queueNode.push(tempNode);
		}
	}

	//队列为空,遍历结束,只需要检查另一个节点如果已经访问过,说明连通
	if( g_visit[endNode] == 1 )
	{
		return true;
	}
	else
	{
		return false;
	}

}



int main(int argc, char* argv[])
{
	int nodeNum ;
	int edgeNum;
	int beginNode;
	int endNode;
	int frontNode;
	int backNode;
	while(cin >> nodeNum >> edgeNum)
	{
		cin >> beginNode >> endNode;
		vector<Node> vecNode[MAXSIZE + 1];

		//到这里N个节点对应的邻接表都创建好了,每个节点的邻接表实际上就是一个向量,每个节点对应于林劫镖中向量下标
		//有向图的邻接表无需复制双份,存在邻接关系,只需要将被指向节点放入节点向量中
		for(int i = 0 ; i < edgeNum ; i++)
		{
			cin >> frontNode >> backNode;
			
			if(frontNode < 0 || backNode < 0)
			{
				continue;
			}
			Node node(backNode);
			vecNode[frontNode].push_back(node);
		}

		bool isPath = isTwoNodeInPath(beginNode , endNode , vecNode);
		if(isPath)
		{
			cout << "exist path" << endl;
		}
		else
		{
			cout << "no exist path" << endl;
		}
	}
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值