图论15-有向图-环检测+度数+欧拉回路

文章目录

  • [1. 有向图设计](#1. 有向图设计)
    • [1.1 私有变量标记是否有向](#1.1 私有变量标记是否有向)
    • [1.2 添加边的处理,双向变单向](#1.2 添加边的处理,双向变单向)
    • [1.3 删除边的处理,双向变单向](#1.3 删除边的处理,双向变单向)
    • [1.4 有向图的出度和入度](#1.4 有向图的出度和入度)
  • [2 有向图的环检测](#2 有向图的环检测)
    • [2.1 普通的算法实现换检测](#2.1 普通的算法实现换检测)
    • [2.2 拓扑排序中的环检测](#2.2 拓扑排序中的环检测)
  • [3 欧拉回路](#3 欧拉回路)

1. 有向图设计

1.1 私有变量标记是否有向

c 复制代码
private boolean directed;
  • 设计接口来判断是否有向:
c 复制代码
public boolean isDirected(){
    return directed;
}

1.2 添加边的处理,双向变单向

遍历文件给出的相邻顶点时,如果邻接表上有节点,就添加一条边。

如果是无向图,反过来添加边。

c 复制代码
adj[a].add(b);

// 如果是无向图
if(!directed)
    adj[b].add(a);

1.3 删除边的处理,双向变单向

cpp 复制代码
public void removeEdge(int v, int w){
    validateVertex(v);
    validateVertex(w);

    if(adj[v].contains(w)) E --;

    adj[v].remove(w);
    if(!directed)
        adj[w].remove(v);
}

1.4 有向图的出度和入度

设计两个数组分别记录对应节点的出度和入度

c 复制代码
private int[] indegrees, outdegrees;

indegrees = new int[V];
outdegrees = new int[V];

添加边的时候,更新相应的度数值

c 复制代码
for(int i = 0; i < E; i ++){
    int a = scanner.nextInt();
    validateVertex(a);
    int b = scanner.nextInt();
    validateVertex(b);

    if(a == b) throw new IllegalArgumentException("Self Loop is Detected!");
    if(adj[a].contains(b)) throw new IllegalArgumentException("Parallel Edges are Detected!");

    adj[a].add(b);

    if(directed){
        outdegrees[a] ++;
        indegrees[b] ++;
    }
    if(!directed)
        adj[b].add(a);
}
  • 度数的接口
c 复制代码
public int degree(int v){
    if(directed)
        throw new RuntimeException("degree only works in undirected graph.");
    validateVertex(v);
    return adj[v].size();
}

public int indegree(int v){
    if(!directed)
        throw new RuntimeException("indegree only works in directed graph.");
    validateVertex(v);
    return indegrees[v];
}

public int outdegree(int v){
    if(!directed)
        throw new RuntimeException("outdegree only works in directed graph.");
    validateVertex(v);
    return outdegrees[v];
}

2 有向图的环检测

2.1 普通的算法实现换检测

设计新的数组记录当前路径.

标记当前路径和标记是否访问过的区别,标记是否访问过时为了避免在dfs过程中检测环的时候重复检测已经访问过的节点。

0-1-2-4-2-1,退回到1 的时候,由于2已经标记访问过,因此下一个节点访问3.

onPath的时候,退回到0-1时,将24重新标记为false,因为已经不在当前路径中:

0-1-2-4

0-1

访问到3的时候onPath为:0-1-3,下一个节点访问1,由于1已经在onPath中,则直接返回环检测结果。

c 复制代码
private boolean[] onPath;
c 复制代码
private boolean dfs(int v){
    visited[v] = true;
    onPath[v] = true;
    for(int w: G.adj(v))
        if(!visited[w]){
            if(dfs(w)) return true;
        }
        else if(onPath[w])
            return true;
            
    onPath[v] = false;
    return false;
}

2.2 拓扑排序中的环检测

能够进行拓扑排序的图是没有环的,否则无法进行拓扑排序。

在拓扑排序的实现过程中,如果返回的res数组中的点的数量与图的点的数量不一致,则说明有环。因为环上的点由于度数无法为0,无法进入队列,从而进入res数组返回答案。

c 复制代码
if(res.size() != G.V()){
    hasCycle = true;
    res.clear();
}

3 欧拉回路

  • 判断出度和入度即可
c 复制代码
private boolean hasEulerLoop(){
    for(int v = 0; v < G.V(); v ++)
        if(G.indegree(v) != G.outdegree(v))
            return false;
    return true;
}
相关推荐
luckys.one1 小时前
第9篇:Freqtrade量化交易之config.json 基础入门与初始化
javascript·数据库·python·mysql·算法·json·区块链
~|Bernard|2 小时前
在 PyCharm 里怎么“点鼠标”完成指令同样的运行操作
算法·conda
战术摸鱼大师2 小时前
电机控制(四)-级联PID控制器与参数整定(MATLAB&Simulink)
算法·matlab·运动控制·电机控制
Christo32 小时前
TFS-2018《On the convergence of the sparse possibilistic c-means algorithm》
人工智能·算法·机器学习·数据挖掘
好家伙VCC3 小时前
数学建模模型 全网最全 数学建模常见算法汇总 含代码分析讲解
大数据·嵌入式硬件·算法·数学建模
liulilittle5 小时前
IP校验和算法:从网络协议到SIMD深度优化
网络·c++·网络协议·tcp/ip·算法·ip·通信
bkspiderx7 小时前
C++经典的数据结构与算法之经典算法思想:贪心算法(Greedy)
数据结构·c++·算法·贪心算法
中华小当家呐8 小时前
算法之常见八大排序
数据结构·算法·排序算法
沐怡旸8 小时前
【算法--链表】114.二叉树展开为链表--通俗讲解
算法·面试
一只懒洋洋9 小时前
K-meas 聚类、KNN算法、决策树、随机森林
算法·决策树·聚类