#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;
}