当前位置:首页 > 力扣 > 力扣1466题:利用BFS解决有向图重排问题

力扣1466题:利用BFS解决有向图重排问题

2天前

力扣1466题:利用BFS解决有向图重排问题 力扣题解 有向图 广度优先搜索 广搜 BFS 图论 树结构 邻接表 第1张

一、题目解读

力扣1466题要求将一个有向图通过最小次数的“边重排”(即反转边方向)转化为一棵。给定n个节点和m条边的有向,需计算最少需要反转的边数,使图成为无环连通图(树)。题目需设计高效算法,避免暴力枚举所有边组合,需利用图论特性或搜索策略优化。

二、解题思路

采用广度优先搜索BFS)结合方向标记的解法,核心思想:

1. 构建邻接表存储边信息,每条边附带方向标记(原始方向/反向)。

2. 从节点0开始BFS遍历图,检查每条边的方向:

○ 若边方向与原图一致(is_original = true),且目标节点未访问,则需反转该边才能形成树,累加反转次数。

○ 若边方向为反向(is_original = false),则直接遍历。

3. 遍历完成后,若所有节点均被访问,说明图可转化为树,返回反转次数;否则无解。

关键在于通过方向标记区分原边与反向边,利用BFS确保树的连通性,避免无效遍历。

三、解题步骤

1. 构建邻接表:

○ 初始化graph为n个空列表,存储节点的出边信息。

○ 遍历connections,对每条边(u, v):

■ 添加(u, v, true)到graph[u],表示原方向边;

■ 添加(v, u, false)到graph[v],表示反向边。

2. 初始化BFS:

○ 标记节点0已访问,将其入队。

3. BFS遍历:

○ 循环直至队列为空,当前节点u出队。

○ 遍历u的所有出边(v, is_original):

■ 若v未访问,分情况处理:

● 若is_original = true(原方向边),说明需反转边才能形成树,累加反转次数res;

● 若is_original = false(反向边),则无需操作。

■ 标记v已访问,将其入队。

4. 结果检查:遍历结束后,若所有节点均被访问,返回res;否则题目无解(图中存在环或未连通)。

四、代码与注释

class Solution {
public:
    int minReorder(int n, vector<vector<int>>& connections) {
        vector<vector<pair<int, bool>>> graph(n); // 邻接表,bool表示方向是否原样
        for (auto& conn : connections) {
            graph[conn[0]].emplace_back(conn[1], true);  // 原始方向
            graph[conn[1]].emplace_back(conn[0], false); // 反向边
        }
        
        vector<bool> visited(n, false);
        queue<int> q;
        q.push(0);
        visited[0] = true;
        int res = 0;
        
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            
            for (auto& [v, is_original] : graph[u]) {
                if (!visited[v]) {
                    if (is_original) res++; // 需要反转的边
                    visited[v] = true;
                    q.push(v);
                }
            }
        }
        return res;
    }
};

注释说明:

● graph[u].emplace_back(v, true):存储原方向边,标记为true;

● if (is_original) res++:当BFS遇到原方向边时,说明该边需反转才能形成树;

● BFS遍历确保树的连通性,方向标记避免重复判断边方向。

五、总结

本文通过BFS算法高效解决有向图重排边问题。核心创新点:

1. 邻接表记录边方向,简化反转判断逻辑;

2. BFS保证遍历顺序,避免环检测的开销;

3. 仅统计原方向边的反转次数,无需验证最终图是否为树。

算法时间复杂度O(n+m),空间复杂度O(n+m),为图论优化问题的典型解法,适用于需快速处理有向图连通性的场景。


原创内容 转载请注明出处

分享给朋友:

相关文章

LeetCode 2523题解:寻找区间内最小间隔质数对(C++代码)

LeetCode 2523题解:寻找区间内最小间隔质数对(C++代码)

一、题目解读LeetCode 2523题要求在一个给定的整数区间 [left, right] 内,找到间隔最小的两个质数(即相邻质数的差值最小),并返回这对质数。若区间内不存在两个质数,则返回 [-1...

力扣LCR074题区间合并算法解析:贪心排序与区间重叠处理

力扣LCR074题区间合并算法解析:贪心排序与区间重叠处理

一、题目解读力扣LCR074题要求对给定的二维区间数组(每个区间由起始点和终止点构成)进行合并,将重叠的区间合并为更宽的区间,最终输出不重叠的合并结果。例如,输入[[1,3],[2,6],[8,10]...

力扣2588题解:利用前缀异或和与哈希表求解美丽子数组问题

力扣2588题解:利用前缀异或和与哈希表求解美丽子数组问题

一、题目解读力扣2588题要求计算给定数组中“美丽子数组”的数量。所谓“美丽子数组”,是指子数组的异或和为0。题目关键在于理解子数组异或和的性质,并通过高效算法统计符合条件的子数组数量。二、解题思路采...

LeetCode 1031题解析:不重叠子数组最大和的解法(前缀和+动态规划)

LeetCode 1031题解析:不重叠子数组最大和的解法(前缀和+动态规划)

一、题目解读LeetCode 1031题要求在不重叠的前提下,从给定数组nums中寻找两个长度分别为firstLen和secondLen的连续子数组,使其和最大。题目强调子数组必须不重叠,即两个子数组...

力扣1643题:第K小字典序路径(附C++代码与解题思路)

力扣1643题:第K小字典序路径(附C++代码与解题思路)

一、题目解读本题要求生成从原点(0, 0)到目标坐标(destination[0], destination[1])的路径中,字典序第K小的路径。路径仅由向下字符'V'(代表垂直移动)...

LeetCode 2466题解:统计构造好字符串的方案数(动态规划+模运算)

LeetCode 2466题解:统计构造好字符串的方案数(动态规划+模运算)

一、题目解读LeetCode 2466题要求统计在长度范围 [low, high] 内,由字符 '0' 和 '1' 构成的“好字符串”数量。好字符串定义为:每次可添加...

发表评论

访客

看不清,换一张

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