当前位置:首页 > 牛客 > 牛客17722题解析:基于拓扑排序的安全客户识别算法及代码实现

牛客17722题解析:基于拓扑排序的安全客户识别算法及代码实现

7小时前

牛客17722题解析:基于拓扑排序的安全客户识别算法及代码实现 拓扑排序 图算法 牛客题解 图 有向图 邻接表 队列结构 队列 第1张

一、题目解读

牛客17722题要求识别一组客户中的“安全客户”,即不存在直接或间接依赖关系的客户。题目给定n个客户和m条依赖关系(u,v表示u依赖v),需要输出所有安全客户的编号。问题本质是判断有向图中的入度为0的节点,可通过拓扑排序解决。

二、解题思路

采用拓扑排序算法。首先构建邻接表存储,计算每个节点的出度。将出度为0的节点入队,通过拓扑排序迭代处理:每当节点出度减为0时,标记其为安全并加入队列,直至队列为空。最终输出所有安全客户编号。核心思想是利用拓扑排序的特性,逐步消除依赖关系,识别无依赖的节点。

三、解题步骤

1. 数据输入与初始化

读取n、m,构建邻接表graph,初始化出度数组out_degree和标记数组is_safe。

2. 构建图与出度计算

遍历m条边(u,v),将v加入u的邻接表,同时out_degree[u]++。

3. 拓扑排序标记安全节点

○ 初始化队列:将出度为0的节点入队并标记为安全。

○ 迭代处理:弹出队首节点u,遍历其所有指向的节点v,将v的出度减1。若v出度减为0且未标记,则标记v为安全并入队。

4. 收集安全客户

遍历is_safe数组,收集所有标记为true的节点编号。

5. 输出结果

若安全列表为空输出"None",否则按编号顺序输出。

四、代码及注释

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

vector<vector<int>> graph;  // 邻接表存储图
vector<int> out_degree;     // 出度数组
vector<bool> is_safe;       // 标记是否为安全客户

void mark_safe_customers(int n) {
    queue<int> q;
    // 初始化:出度为0的节点是安全的
    for (int i = 1; i <= n; ++i) {
        if (out_degree[i] == 0) {
            q.push(i);
            is_safe[i] = true;
        }
    }
    
    // 拓扑排序过程
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        
        // 遍历所有指向u的节点
        for (int v = 1; v <= n; ++v) {
            if (find(graph[v].begin(), graph[v].end(), u)!= graph[v].end()) {
                out_degree[v]--;
                if (out_degree[v] == 0 &&!is_safe[v]) {
                    is_safe[v] = true;
                    q.push(v);
                }
            }
        }
    }
}

int main() {
    int n, m;
    cin >> n >> m;
    
    graph.resize(n + 1);
    out_degree.resize(n + 1, 0);
    is_safe.resize(n + 1, false);
    
    // 读取边关系并构建图
    for (int i = 0; i < m; ++i) {
        int u, v;
        char comma;
        cin >> u >> comma >> v;
        graph[u].push_back(v);
        out_degree[u]++;
    }
    
    mark_safe_customers(n);
    
    // 收集所有安全客户
    vector<int> safe_list;
    for (int i = 1; i <= n; ++i) {
        if (is_safe[i]) {
            safe_list.push_back(i);
        }
    }
    
    // 输出结果
    if (safe_list.empty()) {
        cout << "None";
    } else {
        for (int i = 0; i < safe_list.size(); ++i) {
            if (i > 0) cout << " ";
            cout << safe_list[i];
        }
    }
    
    return 0;
}

五、总结

该代码通过拓扑排序高效解决了安全客户识别问题,时间复杂度为O(n+m)。关键点在于:

1. 利用出度数组快速定位初始安全节点;

2. 通过队列实现拓扑排序的动态更新;

3. 将实际问题转化为图论模型,凸显算法设计的巧妙性。

掌握拓扑排序的应用场景(如依赖关系、任务调度等)能提升解决类似问题的效率。

原创内容 转载请注明出处

分享给朋友:

相关文章

牛客14496题解:括号最大深度问题(栈思想与代码优化)

牛客14496题解:括号最大深度问题(栈思想与代码优化)

一、题目解读牛客14496题要求计算给定括号字符串中的最大深度。例如,对于字符串 "(()())",最大深度为2。题目考察对括号嵌套结构的理解,以及如何通过编程找到最深嵌套层次。二...

牛客NC67题解:汉诺塔递归算法与解题步骤

牛客NC67题解:汉诺塔递归算法与解题步骤

一、题目解读牛客NC67题要求解决汉诺塔问题,这是一个经典的递归算法题目。题目给定整数n,代表汉诺塔中的盘子数量,需要输出将n个盘子从起始柱移动到目标柱的所有步骤。汉诺塔问题规则为:每次只能移动一个盘...

牛客232639题解析:双指针+排序算法高效求解三角形数量(附代码详解)

牛客232639题解析:双指针+排序算法高效求解三角形数量(附代码详解)

一、题目解读牛客232639题要求计算一个整数数组中能够组成有效三角形的三边组合数量。根据三角形不等式,三边需满足任意两边之和大于第三边。例如,数组[3, 4, 5, 6]可组成两个有效三角形([3,...

牛客4432题解题全解析:矩阵快速幂优化楼梯攀登问题(附C++代码)

牛客4432题解题全解析:矩阵快速幂优化楼梯攀登问题(附C++代码)

一、题目解读牛客4432题要求计算在n阶楼梯中,每次可爬1阶或2阶,共有多少种不同的攀登方式。该问题属于经典的动态规划类题目,需通过数学递推或矩阵乘法优化算法以应对较大数据规模。题目核心在于寻找高效计...

洛谷P3694题解:动态规划与状态压缩优化解题全解析

洛谷P3694题解:动态规划与状态压缩优化解题全解析

一、题目解读洛谷P3694题要求解决一个多团队人数分配问题,给定n个元素和m个团队,每个元素属于一个团队,需将元素重新排列,使相邻元素属于不同团队,并最小化调整次数。题目难点在于如何高效处理团队间的空...

牛客4577题解:滑动窗口解法

牛客4577题解:滑动窗口解法

一、题目解读牛客4577题要求处理多组测试数据,每组包含一个整数数组crimes和两个参数n(数组长度)、t(阈值)、c(窗口大小)。题目需要统计数组中所有长度恰好为c的子数组,其元素和不超过t的数量...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。