给定一个无向图, 统计无法互相到达的点对数。
统计无法互相到达点对数
其实还是求联通块,求联通块可以使用搜索进行标记。还要求得联通块中元素的大小。
联通块其实也就是不相交集合,也可以用并查集来做。
每求得一个联通块的元素个数,与之前所有联通块元素个数相乘;
所以本题目两种做法:
并查集的介绍
class Solution {
public:
class UnionFind {
public:
explicit UnionFind(int sz):cnt(sz),pa(sz)
{
iota(pa.begin(), pa.end(), 0);
}
int Find(int k )
{
return k == pa[k] ? k : pa[k] = Find(pa[k]);
}
void Union(int k1, int k2 )
{
int p0 = Find(k1);
int p1 = Find(k2);
if ( p0 != p1) {
pa[p0] = p1;
cnt--;
}
}
int Cnt()
{return cnt;}
private:
vector<int> pa;
int cnt;
};
long long countPairs(int n, vector<vector<int>>& edges) {
UnionFind uf(n);
int sz = edges.size();
for (int i = 0; i < sz; ++i)
uf.Union(edges[i][0], edges[i][1]);
unordered_map<int, int> um;
for (int i = 0; i < n; ++i ) {
um[uf.Find(i)]++;
}
vector<int> node;
for (auto &[k, v]: um) {
node.push_back(v);
}
long long ans = 0;
int pre = 0;
for (int i = 0; i < node.size(); ++i)
ans += 1L * pre * node[i], pre += node[i];
cout << ans << endl;
return ans;
}
};
class Solution {
public:
class UnionFind {
public:
explicit UnionFind(int _sz):cnt(_sz),pa(_sz),sz(_sz, 1)
{
iota(pa.begin(), pa.end(), 0);
}
int Find(int k )
{
return k == pa[k] ? k : pa[k] = Find(pa[k]);
}
void Union(int k1, int k2 )
{
int p0 = Find(k1);
int p1 = Find(k2);
if (p0 == p1)
return ;
if (sz[p0] < sz[p1] ) {
pa[p0] = p1;
sz[p1] += sz[p0];
}
else {
pa[p1] = p0;
sz[p0] += sz[p1];
}
}
int Cnt()
{return cnt;}
int Size(int idx)
{ return sz[idx]; }
private:
vector<int> pa,sz;
int cnt;
};
long long countPairs(int n, vector<vector<int>>& edges) {
UnionFind uf(n);
int sz = edges.size();
for (int i = 0; i < sz; ++i)
uf.Union(edges[i][0], edges[i][1]);
vector<int> node;
for (int i = 0; i < n; ++i) {
if (uf.Find(i) == i)
node.push_back(uf.Size(i));
}
long long ans = 0;
int pre = 0;
for (int i = 0; i < node.size(); ++i)
ans += 1L * pre * node[i], pre += node[i];
return ans;
}
};
class Solution {
public:
void dfs( int i, int &num, vector<vector<int>> &g, vector<bool> &vis) {
++num;
vis[i] = true;
for (int &v: g[i]) {
if (!vis[v]) {
dfs(v, num, g, vis);
}
}
}
long long countPairs(int n, vector<vector<int>>& edges) {
vector<vector<int>> g(n, vector<int>());
vector<bool> vis(n, false);
for (auto &v:edges){
int f = v[0];
int t = v[1];
g[f].push_back(t);
g[t].push_back(f);
}
long long ans = 0;
long long pre = 0;
for (int i = 0; i < n; ++i ) {
if (!vis[i]) {
int num = 0;
dfs( i, num, g, vis);
ans += 1l * pre * num;
pre += num;
}
}
return ans;
}
};
class Solution {
public:
void bfs( int i, int &num, vector<vector<int>> &g, vector<bool> &vis) {
queue<int> nq;
nq.push(i);
++num;
vis[i] = true;
while( !nq.empty() ) {
int idx = nq.front();
nq.pop();
for (auto &v:g[idx]) {
if (!vis[v]) {
nq.push(v);
++num;
vis[v] = true;
}
}
}
}
long long countPairs(int n, vector<vector<int>>& edges) {
vector<vector<int>> g(n, vector<int>());
vector<bool> vis(n, false);
for (auto &v:edges){
int f = v[0];
int t = v[1];
g[f].push_back(t);
g[t].push_back(f);
}
long long ans = 0;
long long pre = 0;
for (int i = 0; i < n; ++i ) {
if (!vis[i]) {
int num = 0;
bfs( i, num, g, vis);
cout << num << endl;
ans += 1l * pre * num;
pre += num;
}
}
return ans;
}
};