有向图判定是否有环

先说句话再插入代码

#include <iostream>

#include <vector>
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;
    system("pause");
    return 0;
}

转自一个不知道名字的博主

https://www.csdn.net/tags/MtjaIgwsMTE2MjktYmxvZwO0O0OO0O0O.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值