1. 程式人生 > >有向圖的DFS遍歷及判斷是否有環(演算法導論)

有向圖的DFS遍歷及判斷是否有環(演算法導論)

程式碼與10月22號已更正, 多謝:

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
const int MAX = 1000;
int color[MAX];
int Time;
bool is_DAG;   // 分別是時間撮,是否有環
int first[MAX],last[MAX];   // 最先被訪問的時間撮,結束訪問的時間撮
#define CLR(arr,val) memset(arr,val,sizeof(arr))
typedef struct
{
	char v[MAX];
	vector<int> map[MAX];
	int vNum;  // 節點數量
	int eNum;  // 邊的數量
}graph;
//頂點顏色表 color[u]
//   0 白色,未被訪問過的節點標白色
//   -1 灰色,已經被訪問過一次的節點標灰色
//      1 黑色,已經被訪問過了(它的後代也全部被訪問過了)
void Create(graph * g);  // 建立圖
void DFS(graph *g);//深度優先遍歷圖g
void dfs(graph *g,int curPoint);//從頂點i開始深度優先遍歷與其相鄰的點
void Create(graph *g)
{
	for(int i = 0;i < g->eNum;i++)    
	{
		int u,v;                  //第一個點是點0, 不是點1
		cin>>u>>v;
		g->map[u].push_back(v);
	}
}
void dfs(graph *g,int curPoint )
{
	cout << "正在訪問節點 : " << curPoint<<endl; 
	color[curPoint] = -1;   // 標記此點位灰色
	Time ++;
	first[curPoint] = Time;
	for(unsigned int i = 0 ; i < g->map[curPoint].size();i++) //遍歷所有和curPoint相連的點
	{
		int now = g->map[curPoint][i];
		if(color[now] == 0)    // 如果點為白色
			dfs(g,now);
		else if(color[now] == -1)
			is_DAG = false;   // 訪問到了反向邊,那麼就是有環了 
	}
	color[curPoint] = 1;     //標記為黑色, 說明點curPoint及其後代被訪問過了
	cout << "節點" << curPoint << "訪問結束" <<endl;
	last[curPoint] = ++Time;
}
void Init(graph *g)
{
	for(int i  = 0;i < g->eNum;i++)
	{
		color[i] = 0;
		first[i] = 0;
		last[i] = 0;
	}
	is_DAG = true;
	Time = 0;
}
void DFS(graph *g)   // 遍歷每一個點
{
	Init(g);   // 別忘了初始化
	for(int i = 0;i < g->vNum; i++)
	{
		if(color[i] == 0)   //如果是白色, 表示沒訪問過
			dfs(g,i);
	}
}
int main()
{
	graph *g = new graph;
	g->vNum = 5;
	g->eNum = 3;   // 初始化邊數和點數
	Create(g);    // 建圖
	DFS(g);       //遍歷圖
	if(is_DAG)
		cout << "這個不是環" <<endl;
	else
		cout << " 是環 " << endl;
	for(int i = 0; i < 5; i++)
		cout << "點" << i << "開始與結束時間戳分別為:" << first[i] << " " << last[i] << endl;
	return 0;
}