2316. 统计无向图中无法互相到达点对数 - 力扣(LeetCode)
法一:并查集
找到父节点为自己的,“所有子节点的数量*(n-子节点数量)”即为该联通图 与其他节点无法到达的点对数
遍历所有联通图加起来,除2(去重)即为所求
class Solution {
public:
static const int N=1e6+10;
int p[N],size[N];
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
void unit(int a,int b){
int pa=find(a),pb=find(b);
if(pa!=pb){
p[pa]=pb;
size[pb]+=size[pa];
}
}
long long countPairs(int n, vector<vector<int>>& edges) {
for(int i=0;i<n;i++){
p[i]=i;
size[i]=1;
}
for(auto edge:edges){
unit(edge[0],edge[1]);
}
long long res=0;
for(int i=0;i<n;i++){
if(p[i]==i){
long long num=(long long )size[i]*(n-size[i]);
res+=num;
}
}
return res/2;
}
};
法二:BFS
构建邻接表,遍历即可,要注意的是单个节点没有添加进邻接表,需要特判size=1.
class Solution {
public:
static const int N=1e6+10;
int e[N],ne[N],h[N],idx=0;
bool vis[N],visi[N];
int size=0;
queue<int>q;
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void bfs(int u){
q.push(u);
while(q.size()){
int cur=q.front();
q.pop();
for(int i=h[cur];i!=-1;i=ne[i]){
int j=e[i];
if(!vis[j]){
vis[j]=true;
size++;
q.push(j);
}
}
}
}
long long countPairs(int n, vector<vector<int>>& edges) {
memset(h,-1,sizeof h);
for(auto edge:edges){
int a=edge[0],b=edge[1];
add(a,b),add(b,a);//无向图 邻接表
visi[a]=true;
visi[b]=true;
}
memset(vis,false,sizeof vis);
long long res=0;
for(int i=0;i<n;i++){
size=0;
if(visi[i])
bfs(i);
else size=1;
//cout<<size<<" ";
res+=(long long)size*(n-size);
}
return res/2;
}
};