2316. 统计无向图中无法互相到达点对数
中等
提示
给你一个整数 n
,表示一张 无向图 中有 n
个节点,编号为 0
到 n - 1
。同时给你一个二维整数数组 edges
,其中 edges[i] = [ai, bi]
表示节点 ai
和 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 <= 105
0 <= edges.length <= 2 * 105
edges[i].length == 2
0 <= ai, bi < n
ai != bi
- 不会有重复边。
题解
class Solution {
public:vector<int> parent;int find(int x) {if (x!=parent[x]) {parent[x]=find(parent[x]);}return parent[x];}void unionSet(int x, int y) {int rootX=find(x);int rootY=find(y);if (rootX!=rootY) {parent[rootX]=rootY;}}long long countPairs(int n, vector<vector<int>>& edges) {parent.resize(n);for (int i=0;i<n;i++) {parent[i]=i;}for (int i=0;i<edges.size();i++) { //易错,不是nunionSet(edges[i][0],edges[i][1]);}unordered_map<int,int> mem;for (int i=0;i<n;i++) {mem[find(i)]++;}long long cnt=0;long long remain=n;for (auto m:mem) {remain-=m.second;cnt+=m.second*remain;}return cnt;}
};
这里后面求和的地方非常巧妙
这是原本的求和思路,每块不连通节点区域,两两相乘
这是优化后的求和思路:
- 初始化 remainingNodes 为节点总数 n,代表初始未考虑的节点数。
- 遍历存储连通分量信息的 mem:
获取当前连通分量节点数 componentSize。
从 remainingNodes 中减去 componentSize,更新未考虑节点数。
将 componentSize 与 remainingNodes 相乘,得到当前连通分量与剩余节点组成的不连通节点对数,累加到 cnt。 - 遍历结束,cnt 即为图中不连通节点对总数。