题目大意:
有一个无向图,让判断是不是所有的点都满足:如果A和B连接并且C和A连接,那么C和A连接。
分析
很明显,让判断图中的连通块是不是全部都是完全图。
完全图的定义:图中任意两点都相连
有个数学公式: 边 = 点 * (点-1) / 2;
找一个无向图中的各个连通块,很明显,并查集
所以这个题就是,用并查集判断图中的各个连通块是不是完全图
完全图: 传送门.
并查集: 传送门.
代码
#include <bits/stdc++.h>
const int maxn = 150010;
using namespace std;
int tree[maxn] = {0}; // 纪录连通块的根
ll dian[maxn] = {0}; // 纪录连通块中的点数
ll bian[maxn] = {0}; // 纪录连通块中的边数
void chushi_(int n){ //初始化,默认每个元素都是一个集合
for(int i = 1; i <= n; i++){
tree[i] = i;
dian[i] = 1;
}
}
int find(int x){ //询问集合的父子节点 找该连通块的根 连通块的根的没有父节点所以是它本身
if(tree[x] == x) return x;
return tree[x] = find(tree[x]);
}
void join(int x, int y){ //更新集合
int fx = find(x);
int fy = find(y);
if(fx != fy){ //如果两个点的父节点不同,则把这两个连通块合并成一个连通块
tree[fy] = fx;
bian[fx] += bian[fy] + 1;
dian[fx] += dian[fy];
}
else{
bian[fx]++;
}
}
bool check(int n){
for(int i = 1; i <= n; i++){
if(tree[i] != i) continue; // 只需要选取连通块的根去做判断
if(bian[i] != dian[i] * (dian[i] - 1) / 2) return false;
}
return true;
}
int main(){
int n, m;
scanf("%d %d", &n, &m);
chushi_(n);
int x, y;
for(int i = 1; i <= m; i++){
scanf("%d %d", &x, &y);
join(x, y);
}
if(check(n)) cout << "YES" << endl;
else cout << "NO" << endl;
return 0;
}
这次的题完全败给了翻译