题目:
题目大意:给定n个由两个数字构成的集合(这些数字都不会超过n) ,要求你把这些集合分成两份,且单份中不能出现相同的数字存在。
解题思路:
1.因为给定了不超过n的两个数的集合
总共就有2n个数
要将2n个数分成两份
那么我们就只能使从1到n的数字都 仅出现 且必须 出现两次
且出现两次这样才能分成两份
2.我们将平分n集合的两份分别取名为
份数1 和 份数2
因为集合将两个数连接到了一起
我们把一个集合放进份数1中
也就意味着那一个集合中的两个数
都相互连接到了一起
我们就可以采用并查集的方法将两个数字连通
最后连通一定分成了两部分(分成其他数量的部分不满足 思路1)
且两部分一定为偶数(若为奇数则代表存在一份数中 有重复数的数出现)
如此按照这两个思路便可以实现该题代码
代码详解:
#include<stdio.h>
#include<iostream>
using namespace std;
int vis[(int)2e5 + 6];
int arr[(int)2e5 + 6];
int sum[(int)2e5 + 6];
int find(int t) {
if (t == vis[t]) return t;
return vis[t] = find(vis[t]);
}
void pre(int n) {
for (int i = 1; i <= n; i++) {
vis[i] = i;
arr[i] = 0;
sum[i] = 0;
}
}
int main() {
int t;
cin >> t;
while (t--) {
int n,a,b;
cin >> n;
pre(n);
for (int i = 1; i <=n; i++) {//并查集的实现
cin >> a >> b;
sum[a]++;
sum[b]++;
vis[find(a)] = find(b);
}
bool flag = 1;
for (int i = 1; i <= n; i++) {//思路1的判断
if (sum[i] != 2) {//因为数字不能超过n,故要想分成两组必须每个数字出现两次
flag = 0;
}
arr[find(i)]++;
}
for (int i = 1; i <= n; i++) {//思路2的判断
if (arr[i] & 1)flag = 0;
}
if (flag == 1) {
cout << "YES" << endl;
}
else {
cout << "NO" << endl;
}
}
return 0;
}
PS:人生得意须尽欢,莫使金樽空对月。