就写到了D, 计算完全连同图的边数那里忘加了小括号,找了很久。
提取题意就是说每个连通图还需要连多少条边才能成为完全连通图。所以就要用并查集了,但在用并查集的时候还要同时统计当前连通图的已有边数,以便于计算还需要多少。
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0)
#define int long long
using namespace std ;
typedef pair<int,int> PII ;
const int N = 1e6 + 10 ;
const int INF = 0x3f3f3f3f ;
const int MOD = 998244353 ;
int T ;
int n, m;
int a[N] ;
int b[N] ;
vector<PII> op ;
PII p[N] ;
int find(int k){
if(p[k].second != k){
p[k].second = find(p[k].second) ;
}
return p[k].second ;
}
void merge(int a,int b){
if(find(a) != find(b)) p[find(a)].first += p[find(b)].first + 1 ;//不同集合,加上另一集合的边数再加1
else{
p[find(a)].first ++ ;//同一集合只加一条
}
p[find(b)].second = find(a) ;
}
int calc(int k){
return (k * (k - 1)) / 2 ;
}
void solve(){
cin >> n >> m ;
for(int i = 1 ; i <= n ; ++ i){
p[i].second = i ;
p[i].first = 0 ;
}
int l, r ;
set<PII> se ;
for(int i = 1; i <= m ; ++ i){
cin >> l >> r ;
if(se.find({l,r}) == se.end()){
se.insert({l,r}) ;
se.insert({r,l}) ;
merge(l,r) ;
}
}
map<int,int> mp ;
int sum = 0 ;
for(int i = 1 ; i <= n ; ++ i){
mp[p[find(i)].second] ++ ;
}
// cout << mp.size() << endl ;
for(auto e:mp){
sum += calc(e.second) - p[e.first].first ;
// cout << e.first <<" "<< p[e.first].first << " " << e.second << endl ;
}
cout << sum << endl ;
return ;
}
signed main(){
IOS ;
// cin >> T ;
T = 1 ;
while(T--){
solve() ;
}
return 0 ;
}