Leetcode.2316 统计无向图中无法互相到达点对数

题目链接

Leetcode.2316 统计无向图中无法互相到达点对数 rating : 1604

题目描述

给你一个整数 n n n ,表示一张 无向图 中有 n n n 个节点,编号为 0 0 0 到 n − 1 n - 1 n−1 。同时给你一个二维整数数组 e d g e s edges edges ,其中 e d g e s [ i ] = [ a i , b i ] edges[i] = [a_i, b_i] edges[i]=[ai,bi] 表示节点 a i a_i ai 和 b i b_i bi 之间有一条 无向 边。

请你返回 无法互相到达 的不同 点对数目

示例 1:

输入:n = 3, edges = [[0,1],[0,2],[1,2]]

输出:0

解释:所有点都能互相到达,意味着没有点对无法互相到达,所以我们返回 0 。

示例 2:

输入:n = 7, edges = [[0,2],[0,5],[2,4],[1,6],[5,4]]

输出:14

解释:总共有 14 个点对互相无法到达:

\[0,1\],\[0,3\],\[0,6\],\[1,2\],\[1,3\],\[1,4\],\[1,5\],\[2,3\],\[2,6\],\[3,4\],\[3,5\],\[3,6\],\[4,6\],\[5,6\]

所以我们返回 14 。

提示:
  • 1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1≤n≤105
  • 0 ≤ e d g e s . l e n g t h ≤ 2 ∗ 1 0 5 0 \leq edges.length \leq 2 * 10^5 0≤edges.length≤2∗105
  • e d g e s [ i ] . l e n g t h = 2 edges[i].length = 2 edges[i].length=2
  • 0 ≤ a i , b i < n 0 \leq a_i, b_i < n 0≤ai,bi<n
  • a i ≠ b i a_i \neq b_i ai=bi
  • 不会有重复边。

解法:dfs

无法到达的点对,假设其分别为 a a a 和 b b b ,那么这两个点一定是 不可达 的,说明两个点一定是在不同的 连通块

所以我们第一步就要求出所有的 连通块 以及 连通块中的节点数量

如上图, 3 3 3 个连通块,节点数量分别为 : 2 , 3 , 4 2 , 3 ,4 2,3,4。

如果我们要 不重不漏 的计算所有 点对数,可以从左到右的计算:

  • 对于 第一个连通块 ,它的右侧有两个连通块,节点数量分别是 3 , 4 3,4 3,4 与它进行配对,所以一共有 2 × ( 3 + 4 ) = 14 2 \times (3+4) = 14 2×(3+4)=14;
  • 对于 第二个连通块 ,它的右侧有一个连通块,节点数量是 4 4 4 与它进行配对,所以一共有 3 × 4 = 12 3 \times 4 = 12 3×4=12;

所以一共有 14 + 12 = 26 14 + 12 = 26 14+12=26 个点对。

时间复杂度: O ( n ) O(n) O(n)

C++代码:

cpp 复制代码
using LL = long long;

class Solution {
public:
    long long countPairs(int n, vector<vector<int>>& edges) {
        vector<vector<int>> g(n);

        for(auto &e:edges){
            int a = e[0] , b = e[1];
            g[a].push_back(b);
            g[b].push_back(a);
        }

        int f[n];
        memset(f,-1,sizeof f);

        function<int(int)> dfs = [&](int u) ->int{
            int ans = 1;
            f[u] = 1;

            for(auto v:g[u]){
                if(f[v] != -1) continue;
                ans += dfs(v);
            }

            return ans;
        };


        vector<int> vec;
        for(int i = 0;i < n;i++){
            if(f[i] == 1) continue;
            int x = dfs(i);
            vec.push_back(x); 
        }


        LL ans = 0;
        for(int i = 0;i < vec.size() - 1;i++){
            n -= vec[i];
            ans += vec[i] * 1LL * n;
        }

        return ans;

    }
};
相关推荐
仟濹14 天前
【算法打卡day10(2026-02-24 周二)复习算法:DFS BFS 并查集】
算法·深度优先·图论·dfs·bfs·广度优先·宽度优先
List<String> error_P16 天前
DFS(深度优先搜索)
数据结构·算法·dfs
漂流瓶jz18 天前
UVA-12569 树上的机器人规划(简单版) 题解答案代码 算法竞赛入门经典第二版
算法·图论·dfs·bfs·uva·算法竞赛入门经典第二版·11214
玄〤18 天前
枚举问题的两大利器:深度优先搜索(DFS)与下一个排列(Next Permutation)算法详解(Java版本)(漫画解析)
java·算法·深度优先·dfs
漂流瓶jz19 天前
UVA-11214 守卫棋盘 题解答案代码 算法竞赛入门经典第二版
c++·算法·dfs·aoapc·算法竞赛入门经典·迭代加深搜索·八皇后
漂流瓶jz21 天前
UVA-1604 立体八数码问题 题解答案代码 算法竞赛入门经典第二版
算法·ida·深度优先·图论·dfs·bfs·迭代加深搜索
Bear on Toilet23 天前
递归_二叉树_48 . 二叉树最近公共祖先查找
数据结构·算法·二叉树·dfs
罗湖老棍子1 个月前
星际能量矩阵:树形 DP 的递归与非递归双解
算法·动态规划·dfs·bfs·树型dp·树型动态规划
仟濹1 个月前
【算法打卡day7(2026-02-12 周四)算法:BFS and BFS】10__卡码网110_字符串迁移, 11_卡码网105_有向图的完全连通
算法·深度优先·dfs·bfs·宽度优先
源代码•宸1 个月前
Leetcode—200. 岛屿数量【中等】
经验分享·后端·算法·leetcode·面试·golang·dfs