CF 1702E - Split Into Two Sets

文章描述了一个关于多米诺骨牌的问题,给定一系列包含两个不同数字的骨牌,目标是判断是否能将它们分成两组,每组的数字都不重复。解决方案涉及到图论,需要找到所有骨牌之间的关系并确保每个数字出现次数为偶数,且形成的环的顶点数也是偶数。给出的代码通过查找连通分量和计数来判断是否可能。
摘要由CSDN通过智能技术生成

Split Into Two Sets

Polycarp was recently given a set of n n n (number n n n — even) dominoes. Each domino contains two integers from 1 1 1 to n n n.
Can he divide all the dominoes into two sets so that all the numbers on the dominoes of each set are different? Each domino must go into exactly one of the two sets.
For example, if he has 4 4 4 dominoes: { 1 , 4 1,4 1,4}, { 1 , 3 1,3 1,3}, { 3 , 2 3,2 3,2} and { 4 , 2 4,2 4,2}, then Polycarp will be able to divide them into two sets in the required way. The first set can include the first and third dominoes ({ 1 , 4 1,4 1,4} and { 3 , 2 3,2 3,2}), and the second set — the second and fourth ones ({ 1 , 3 1,3 1,3} and { 4 , 2 4,2 4,2}).
 
Input
The first line contains a single integer t ( 1 ≤ t ≤ 1 0 4 ) t (1≤t≤10^4) t(1t104) — the number of test cases.
The descriptions of the test cases follow.
The first line of each test case contains a single even integer n ( 2 ≤ n ≤ 2 ⋅ 1 0 5 ) n (2≤n≤2⋅10^5) n(2n2105) — the number of dominoes.
The next n n n lines contain pairs of numbers a i a_i ai and b i ( 1 ≤ a i , b i ≤ n ) b_i (1≤a_i,b_i≤n) bi(1ai,bin) describing the numbers on the i i i-th domino.
It is guaranteed that the sum of n n n over all test cases does not exceed 2 ⋅ 1 0 5 2⋅10^5 2105.
 
Output
For each test case print:

  • YES, if it is possible to divide n dominoes into two sets so that the numbers on the dominoes of each set are different;
  • NO, if this is not possible.

You can print YES and NO in any case (for example, the strings yEs, yes, Yes and YES will be recognized as a positive answer).
 
Example
input

6
4
1 2
4 3
2 1
3 4
6
1 2
4 5
1 3
4 6
2 3
5 6
2
1 1
2 2
2
1 2
2 1
8
2 1
1 2
4 3
4 3
5 6
5 7
8 6
7 8
8
1 2
2 1
4 3
5 3
5 4
6 7
8 6
7 8

output

YES
NO
NO
YES
YES
NO

Note
In the first test case, the dominoes can be divided as follows:

  • First set of dominoes: [{ 1 , 2 1,2 1,2},{ 4 , 3 4,3 4,3}]
  • Second set of dominoes: [{ 2 , 1 2,1 2,1},{ 3 , 4 3,4 3,4}]

In other words, in the first set we take dominoes with numbers 1 1 1 and 2 2 2, and in the second set we take dominoes with numbers 3 3 3 and 4 4 4.
In the second test case, there’s no way to divide dominoes into 2 2 2 sets, at least one of them will contain repeated number.

题目大意
给你 n n n 个由两个整数( 1 1 1 ~ n n n )组成的多米诺骨牌,将这些牌分成两个组,每组中牌上出现过的数字不同,如果可以分成这样的两组,输出YES,否则输出NO。
(个人认为是 n n n 个序偶)
解题思路
先考虑可以分成符合要求的两组的条件,当我们把每一个多米诺骨牌上的两个数看成是之间有关系时(用图表示),就会发现它们构成了至少一个环(回路),那么每个数只能是出现两次(有向图的对称),为了能分成两组那么每个环上的顶点个数为偶数。得到这么一个环后,然后隔一个分为同一组,就可以分为不重复的两组了。
经过以上的得出的结论,我们可以得知无法分成两组的情况:

  • 某个数出现个数超过 2 2 2 次,或不足 2 2 2 次。
    (我们可以只考虑超过 2 次的,因为有多的,就会导致有少的,甚至没有。最后一定会有重复的)
  • 某个回路中的顶点个数为奇数。
#include <bits/stdc++.h>
using namespace std;

const int N =2e5+10;
int f[N], c[N]; //节点对应父节点 //环中的顶点数

int find(int x) //找到该顶点的父节点 (若为环则是环的根节点
{
    if(f[x] != x)
        f[x] = find(f[x]);
    return f[x];
}

void join(int a, int b) //将 b 节点加入到 a 的连通图中
{
    int fa = find(a);
    int fb = find(b);
    if(fa != fb)
    {
        f[fb] = fa;
        c[fa] += c[fb]; //该连通图根节点所连接的结点个数
    }
}

int main()
{
    int t; cin>>t;
    while(t--)
    {
        int n; cin>>n;
        for(int i=1; i<=n; i++)
        {
            f[i] = i; //初始化父节点
            c[i] = 1; //初始化每个结点的连接个数 (默认就自己为一个顶点,则为 1
        }
        map<int, int> cnt;
        bool flag = true;
        for(int i=1; i<=n; i++)
        {
            int a, b; cin>>a>>b;
            cnt[a]++, cnt[b]++;
            if(cnt[a]>2 || cnt[b]>2) //某个数出现超过 2 次就无法分成两组
                flag = false;
            join(a, b);
        }
        for(int i=1; flag && i<=n; i++)
        {
            if(c[find(i)] & 1) //顶点所在的环中顶点数不是 偶数 就无法分成两组
                flag = false;
        }
        cout<<(flag? "YES\n": "NO\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花生ono

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值