DFS判断回路,仅需一个栈保存每一次的路径,然后判断该路径是否存在回路即可,具体看代码即可
#include"Graph.h"
#include<iostream>
#include<vector>
void __topSort_DFS(Graph & G, int u, vector<int> & visited, short & cycleNum, stack<int> path ) {
visited[u] = true;
path.push(u); // 将当前结点加入路径
// 遍历u每一个邻接点v
for(int v = G.FirstNeighbor(u); v >= 0 ;v = G.NextNeighbor(u, v)) {
if(!visited[v])
__topSort_DFS(G, v, visited, cycleNum, path);
// 对于已访问过的邻接点,需要判断其是否构成回路(当然,path需要至少3个结点才能构成回路)
else
if(path.size() >= 3 ){
// 如果边u->v指向路径上的一个结点(路径上的结点都是已访问结点),说明存在一条回路
// path.size()-2的目的就是排除路径中最近的两个结点:结点u自身和结点u的前驱结点,因为这两种情况不能形成回路
for(int i = 0;i < path.size()-2;++i) {
if(topSeq[i] == v)
cycleNum++;
}
}
}
path.pop(); // 当遍历一条路径到尽头时,便会随着路径进行回溯,于是将当前结点出栈以回溯
}
// 使用DFS判断回路
void topSort_DFS(Graph & G) {
vector<int> visited(G.vexNum, false);
stack<int> path; // 存放DFS每一次可能的路径
short cycleNum = 0; // 可记录图中存在的回路数量
// 遍历所有的连通分量
for(int u = 0; u < G.vexNum ; ++u) {
if(!visited[u]) {
cycleNum = false; // 对于每一个连通分量都判断回路
__topSort_DFS(G, u, visited, cycleNum, path);
}
}
cout << "回路个数为:" << cycleNum << endl;
}
void fun1() {
GraphAM G;
G.vexNum = 5;
G.edge[0][1] = 1;
G.edge[1][3] = 1;
G.edge[2][3] = 1;
G.edge[2][4] = 1;
G.edge[3][4] = 1;
G.edge[4][2] = 1;
G.edge[2][1] = 1;
G.edge[2][0] = 1;
topSort_DFS(G);
}
void fun2() {
GraphAL G;
G.vexNum = 5;
G.adj[0].push_back({1, 1});
G.adj[1].push_back({3, 1});
G.adj[2].push_back({3, 1});
G.adj[2].push_back({4, 1});
G.adj[3].push_back({4, 1});
G.adj[4].push_back({2, 1});
G.adj[2].push_back({1, 1});
G.adj[2].push_back({0, 1});
topSort_DFS(G);
}
int main() {
fun1();
fun2();
return 0;
}
Graph.h:
#include<iostream>
#include<vector>
using namespace std;
// 图——抽象数据结构
struct Graph {
public:
static const int MAXVERTEX;
static const int INF;
int vexNum; // 顶点数
int arcNum; // 边数
virtual int FirstNeighbor(int u) = 0; // 寻找点u的第一个邻接点
virtual int NextNeighbor(int u, int v) = 0; // 寻找处于邻接点v的下一个兄弟邻接点(都是u的邻接点)
virtual bool HasEdge(int u, int v) = 0; // 是否有边(u->v)
virtual int GetEdgeValue(int u, int v) = 0; // 获取边(u->v)的权重
virtual vector<int> GetInDegree() = 0; // 得到该图的入度表
};
const int Graph::INF = 0xffffff;
const int Graph::MAXVERTEX = 100;
// 图——邻接矩阵表示
struct GraphAM: public Graph {
int edge[MAXVERTEX][MAXVERTEX]; // 存放边权重
GraphAM() {
for(int i = 0; i < MAXVERTEX ;++i)
for(int j = 0; j < MAXVERTEX ;++j)
edge[i][j] = INF;
}
int FirstNeighbor(int u) override {
for(int i = 0;i < this->vexNum;i++)
if(this->edge[u][i] != INF)
return i;
return -1;
}
int NextNeighbor(int u, int v) override {
for(int i = v+1; i < this->vexNum ;i++)
if(this->edge[u][i] != INF)
return i;
return -1;
}
bool HasEdge (int u, int v) override { return edge[u][v] != INF; }
int GetEdgeValue(int u, int v) override { return edge[u][v]; }
vector<int> GetInDegree() override {
vector<int> inDegree(vexNum);
for(int j = 0; j < vexNum ;++j) {
for(int i = 0; i < vexNum ;++i) {
if( edge[i][j] != INF ) {
inDegree[j]++;
}
}
}
return inDegree;
}
};
// 图——邻接表表示
struct GraphAL: public Graph {
// 弧信息
struct ArcNode {
int v; // 表弧头,即u->v 中的v
int data;
};
vector<ArcNode> adj[MAXVERTEX]; // 邻接表,adj[u][i]存储了u的第i个邻接边的信息
GraphAL() {}
int FirstNeighbor(int u) override {
// cout << "FirstNeighbor(u) = " << ((this->adj[u].size() > 0) ? this->adj[u][0] : -1) << endl;
return (this->adj[u].size() > 0) ? this->adj[u][0].v : -1;
}
int NextNeighbor(int u, int v) override {
for(int i = 0; i < this->adj[u].size()-1 ;++i)
if(this->adj[u][i].v == v) {
// cout << "NextNeighbor(u, v) = " << this->adj[u][i+1] << endl;
return this->adj[u][i+1].v;
}
return -1;
}
bool HasEdge(int u, int v) override {
for(const ArcNode & i: adj[u])
if(i.v == v)
return true;
return false;
}
int GetEdgeValue(int u, int v) override {
for(const ArcNode & i: adj[u])
if(i.v == v)
return i.data;
throw logic_error("u->v not exist");
}
vector<int> GetInDegree() override {
vector<int> inDegree(vexNum);
for(const vector<ArcNode> & vec: adj)
for(const ArcNode & next: vec)
inDegree[next.v]++;
return inDegree;
}
};