題目連結:https://codeforces.com/problemset/problem/771/A
影片講解:https://www.bilibili.com/video/BV1tZ1FYPELp/?p=6
題目大意:判斷一個無向圖中的每個連通塊是否都是一個完全圖。
首先我們可以用並查集維護每個連通塊的大小。
其次,我們可以開一個 \(cnt_i\) 表示以節點 \(i\) 為根的連通塊中包含多少條邊。
則對於每個連通塊的根節點 \(i\),必須滿足 \(\frac{ sz_i \times (sz_i - 1) }{2} = cnt_i\) 才是 YES
;否則,是 NO
。(這裡 \(sz_i\) 表示以 \(i\) 為根的連通塊的大小,即這個連通塊中的節點個數)
示例程式:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1.5e5 + 5;
int n, m, f[maxn], sz[maxn], cnt[maxn];
struct Edge {
int u, v;
} e[maxn];
void init() {
for (int i = 1; i <= n; i++)
f[i] = i, sz[i] = 1;
}
int find(int x) {
return x == f[x] ? x : f[x] = find(f[x]);
}
void funion(int x, int y) {
int a = find(x), b = find(y);
if (a != b) {
f[b] = a;
sz[a] += sz[b];
}
}
int main() {
scanf("%d%d", &n, &m);
init();
for (int i = 0; i < m; i++) {
scanf("%d%d", &e[i].u, &e[i].v);
funion(e[i].u, e[i].v);
}
for (int i = 0; i < m; i++) {
cnt[find(e[i].u)]++;
}
for (int i = 1; i <= n; i++) {
if (i == find(i)) {
if ((long long)sz[i] * (sz[i] - 1) / 2 != cnt[i]) {
puts("NO");
return 0;
}
}
}
puts("YES");
return 0;
}