Split Into Two Sets
题意:
P最近准备多米诺骨牌,每张多米诺骨牌包含两个数字从1 ~ n, 他能把多米诺骨牌分配给两个集合使得每个集合中的元素都是不相同的吗? 每张多米诺骨牌只能去一个集合
思路:
先考虑特殊的,如果牌的数字重复,一个数字出现 >= 3, 牌的数量是奇数,这些就是不可能的,而且每个数字1 ~ n都必须出现2次,有了以上的条件就可以发现剩下的数字必然构成的都是环,而且只要每个环的数字个数为偶数个,那就是YES,否则就是NO,问题就转换为求求一个个集合环的数量,这个可以用并查集进行实现,详细看代码
总结:
并查集可以判断环,可以求一个联合集合的数字数量,收获很大😊
点击查看代码
#include <bits/stdc++.h>
#define endl '\n'
#define IOS ios::sync_with_stdio(false);
using namespace std;
typedef long long ll;
const ll MAXN = 2e5 + 10;
ll T, n, k;
ll a[MAXN], b[MAXN];
ll fa[MAXN], sz[MAXN];
vector<ll> edge[MAXN];
void Init()
{
for (int i = 1; i <= n; ++i)
{
fa[i] = i;
edge[i].clear();
sz[i] = 1; //刚开始都有自身节点
}
}
ll find(ll x)
{
if (x == fa[x])
return x;
else
return fa[x] = find(fa[x]);
}
bool merge(ll x, ll y)
{
ll fax = find(x);
ll fay = find(y);
if (fax == fay) //说明此处存在环
return true;
else
{
fa[fax] = fay;
sz[fay] += sz[fax];
return false;
}
}
int main()
{
IOS; cin.tie(0), cout.tie(0);
cin >> T;
while (T--)
{
cin >> n;
Init();
map<ll, ll> mp;
bool flag = true;
for (int i = 1; i <= n; ++i)
{
cin >> a[i] >> b[i];
mp[a[i]]++;
mp[b[i]]++;
if (a[i] == b[i] || mp[a[i]] >= 3 || mp[b[i]] >= 3)
{
flag = false;
}
}
if (mp.size() != n)
flag = false;
for (auto it = mp.begin(); it != mp.end(); ++it)
{
if (it->second != 2)
flag = false;
}
if (flag == false)
{
cout << "NO" << endl;
continue;
}
//我感觉剩下的情况肯定是可以构成环,而且没有多余的数字
for (int i = 1; i <= n; ++i)
{
merge(a[i], b[i]);
}
for (int i = 1; i <= n; ++i)
{
if (find(i) != i) //说明这个不是并查集集合的头
continue;
if (sz[find(i)] & 1)
{
flag = false;
break;
}
}
if (flag)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}
标签:
并查集求每个集合的数字数量
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具