首页 > 其他分享 >【图的连通性】【并查集】【拓扑排序】

【图的连通性】【并查集】【拓扑排序】

时间:2024-05-14 16:12:51浏览次数:10  
标签:std 连通性 parent int 拓扑 查集 排序 addEdge

在图论中,不同类型的图(无向图和有向图)需要使用不同的算法和数据结构来处理它们的特性和问题。这里我们将讨论如何使用并查集来解决无向图的连通性问题,以及如何使用深度优先搜索(DFS)、广度优先搜索(BFS)和拓扑排序来解决有向图中的依赖性问题。

无向图的连通性:并查集

对于无向图的连通性问题,并查集(Union-Find)是一个非常有效的数据结构。它可以用于快速合并集合和查找元素所属的集合,从而帮助我们判断两个节点是否在同一个连通分量中。

示例:判断无向图的连通性

#include <vector>
#include <iostream>

class UnionFind {
public:
    UnionFind(int n) {
        parent.resize(n);
        rank.resize(n, 0);
        for (int i = 0; i < n; ++i) {
            parent[i] = i;
        }
    }
    
    int find(int x) {
        if (parent[x] != x) {
            parent[x] = find(parent[x]); // 路径压缩
        }
        return parent[x];
    }
    
    bool unionSet(int x, int y) {
        int rootX = find(x);
        int rootY = find(y);
        if (rootX == rootY) {
            return false; // x 和 y 已经在同一个集合中
        }
        if (rank[rootX] > rank[rootY]) {
            parent[rootY] = rootX;
        } else if (rank[rootX] < rank[rootY]) {
            parent[rootX] = rootY;
        } else {
            parent[rootY] = rootX;
            rank[rootX]++;
        }
        return true;
    }

private:
    std::vector<int> parent;
    std::vector<int> rank;
};

int main() {
    int n = 5; // 节点数
    UnionFind uf(n);
    
    // 添加边
    std::vector<std::pair<int, int>> edges = {{0, 1}, {1, 2}, {3, 4}};
    for (const auto& edge : edges) {
        uf.unionSet(edge.first, edge.second);
    }
    
    // 检查连通性
    std::cout << "0 and 2 are connected: " << (uf.find(0) == uf.find(2)) << std::endl; // 输出 1 (true)
    std::cout << "0 and 4 are connected: " << (uf.find(0) == uf.find(4)) << std::endl; // 输出 0 (false)
    
    return 0;
}

有向图的依赖性:DFS、BFS、拓扑排序

对于有向图的依赖性问题,例如检测是否存在环、确定任务的执行顺序等,我们通常使用深度优先搜索(DFS)、广度优先搜索(BFS)以及拓扑排序。

拓扑排序

拓扑排序是一种对有向无环图(DAG)进行排序的方法,使得对于每条边 ( u \to v ),顶点 ( u ) 在排序后序列中出现在顶点 ( v ) 之前。

使用 DFS 进行拓扑排序
#include <vector>
#include <stack>
#include <iostream>

class Graph {
public:
    Graph(int vertices) : adj(vertices), V(vertices) {}
    
    void addEdge(int u, int v) {
        adj[u].push_back(v);
    }
    
    void topologicalSort() {
        std::vector<bool> visited(V, false);
        std::stack<int> Stack;
        
        for (int i = 0; i < V; i++) {
            if (!visited[i]) {
                topologicalSortUtil(i, visited, Stack);
            }
        }
        
        // 打印拓扑排序
        while (!Stack.empty()) {
            std::cout << Stack.top() << " ";
            Stack.pop();
        }
        std::cout << std::endl;
    }

private:
    int V;
    std::vector<std::vector<int>> adj;
    
    void topologicalSortUtil(int v, std::vector<bool>& visited, std::stack<int>& Stack) {
        visited[v] = true;
        
        for (int i : adj[v]) {
            if (!visited[i]) {
                topologicalSortUtil(i, visited, Stack);
            }
        }
        
        Stack.push(v);
    }
};

int main() {
    Graph g(6);
    g.addEdge(5, 2);
    g.addEdge(5, 0);
    g.addEdge(4, 0);
    g.addEdge(4, 1);
    g.addEdge(2, 3);
    g.addEdge(3, 1);
    
    std::cout << "拓扑排序结果: ";
    g.topologicalSort();
    
    return 0;
}
使用 Kahn 算法(BFS)进行拓扑排序
#include <vector>
#include <queue>
#include <iostream>

class Graph {
public:
    Graph(int vertices) : adj(vertices), V(vertices) {}

    void addEdge(int u, int v) {
        adj[u].push_back(v);
    }

    void topologicalSort() {
        std::vector<int> in_degree(V, 0);

        for (int u = 0; u < V; u++) {
            for (int v : adj[u]) {
                in_degree[v]++;
            }
        }

        std::queue<int> q;
        for (int i = 0; i < V; i++) {
            if (in_degree[i] == 0) {
                q.push(i);
            }
        }

        int count = 0;
        std::vector<int> top_order;

        while (!q.empty()) {
            int u = q.front();
            q.pop();
            top_order.push_back(u);

            for (int v : adj[u]) {
                if (--in_degree[v] == 0) {
                    q.push(v);
                }
            }

            count++;
        }

        if (count != V) {
            std::cerr << "存在环,无法进行拓扑排序。" << std::endl;
            return;
        }

        for (int i : top_order) {
            std::cout << i << " ";
        }
        std::cout << std::endl;
    }

private:
    int V;
    std::vector<std::vector<int>> adj;
};

int main() {
    Graph g(6);
    g.addEdge(5, 2);
    g.addEdge(5, 0);
    g.addEdge(4, 0);
    g.addEdge(4, 1);
    g.addEdge(2, 3);
    g.addEdge(3, 1);
    
    std::cout << "拓扑排序结果: ";
    g.topologicalSort();
    
    return 0;
}

解释

  1. DFS 拓扑排序

    • 通过递归访问每个节点,并在所有相邻节点都访问完后,将当前节点压入栈中。
    • 最后从栈中弹出节点就是拓扑排序的顺序。
  2. Kahn 算法(BFS 拓扑排序)

    • 计算每个节点的入度。
    • 将所有入度为0的节点入队。
    • 不断从队列中取出入度为0的节点,加入拓扑排序序列,并减少其相邻节点的入度。
    • 如果在排序结束时仍存在入度不为0的节点,则说明图中存在环。

适用场景

  • 无向图的连通性问题:使用并查集。
  • 有向图的依赖性问题:使用DFS或BFS进行拓扑排序。

标签:std,连通性,parent,int,拓扑,查集,排序,addEdge
From: https://www.cnblogs.com/peterzh/p/18191504

相关文章

  • 运维自动化新篇章:从业务到拓扑,一键构建集群模块
    业务,是蓝鲸CD体系中比较重要的概念和维度,日常使用中主机、进程、业务拓扑的管理都需要依赖已经存在的业务,其他蓝鲸体系产品也基本上都是围绕业务的维度来提供对应的服务和相关的鉴权。1、创建业务/业务集请确保有创建业务的权限,一般可以由管理员创建或申请创建业务的权限资......
  • [LeetCode] 1584.连接所有点的最小费用 Kruskal And Prim 算法 Java 并查集
    Problem:1584.连接所有点的最小费用目录Kruskal算法复杂度CodePrim算法复杂度CodeKruskal算法复杂度时间复杂度:添加时间复杂度,示例:$O(mlog(m))$空间复杂度:添加空间复杂度,示例:$O(n)$CodeclassSolution{publicintminCostConnectPoints(int[][]po......
  • 【拓扑排序】【DFS】课程表
    题源解法1DFS思路:最先被放入栈中的节点是在拓扑排序中最后面的节点一开始用了DFS,但是出现了问题DFS函数在正确处理循环检测方面存在问题:循环检测逻辑问题:在您的DFS中,您检查一个课程是否已被访问,如果已被访问,则立即将valid设置为False。这种方式并没有正确区分处于当前路......
  • 【网络知识系列】-- 网络安全设备应用部署拓扑图
    AI防火墙应用大中型企业边界防护内网管控与安全隔离云数据中心安全联动传统数据中心边界防护AntiDDoS防御系统应用城域网防护数据中心防护IPS新一代入侵防御系统应用互联网边界出口:对出口带宽精细控制,防止带宽滥用;保护内网免受外网攻击。数据中心服务器前端:抵御......
  • 图 - 存储结构 & 最短路径 & 最小生成树 & 拓扑排序 & 关键路径
    图的四种存储结构邻接矩阵有一个存储顶点的顺序表和一个存储边/弧的二维数组。存储结构#defineMaxInt32767#defineMVNum100//最大顶点数typedefstruct{VerTexTypevexs[MVNum];//顶点顺序表ArcTypearcs[MVNum][MVNum];//邻接矩阵intvexnum,arcn......
  • [笔记]拓扑排序
    对于一个有向无环图(DAG)的顶点按顺序排成一个序列的过程,就是拓扑排序(TopologicalSort)。具体来说,这个序列必须满足:每个顶点正好出现\(1\)次。如果图上存在一条\(A\toB\)的路径,那么\(A\)一定在\(B\)之前。注意:拓扑排序结果可能不唯一。具体做法就是每次在图中寻找\(1\)个入......
  • 服务器分层拓扑架构图形化显示工具
    目录服务器分层拓扑架构图形化显示工具---HWLOC下载依赖包安装源码编译安装执行命令示例显示PCI层次结构参考文档服务器分层拓扑架构图形化显示工具---HWLOC 可移植硬件局部(hwloc)软件包提供了现代架构分层拓扑的可移植抽象(跨操作系统、版本、体系结构等),包括NUMA内......
  • 并查集
    并查集并查集模板包含路径压缩+小挂大constintMAXN=1e5+1;intfather[MAXN];//存父亲节点father[1]=2指的是1节点的父亲为2intsize[MAXN]; //存每个集合的大小intstack[MAXN];//intn;//建立并查集voidbuild(){ for(inti=0;i<=n;i++)......
  • 【网络知识系列】-- 网络拓扑图S
    一、整体技术体系架构产品清单:下一代防火墙、数据库审计、负载均衡、感知平台+(检测探针)......
  • ITIL4服务价值系统(SVS)与莫比乌斯环:无限服务优化的拓扑之旅
    莫比乌斯环:单一而无限的象征莫比乌斯环,这个拓扑学上的奇观,以其独特的一体两面特性,完美地映射了ITIL4服务价值系统的精髓。它象征着无限、统一和连续性,提示我们看待事物时应超越传统二元对立的视角,理解事物间深刻的内在联系和连续性。ITIL4服务价值链:莫比乌斯上的价值流转正如......