Codeforces Round #805 (Div. 3)

题目链接

E. Split Into Two Sets

题意

给出若干个骨牌,每个骨牌上写有两个数字,问能否把骨牌分成两堆,使得每堆中不存在重复的数字.

思路

转化成图论问题,令每个数字对应一个节点,问题从将牌分成两个集合转换成将数字分成两个集合。

对于牌(x,y),在点x和点y之间连边,表示选了x就得选y。

如果图中存在奇环,那么就无解;反之则有解。

代码

复制代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl "\n"
const ll N = 2e5 + 233, mod = 1e9 + 7;
int n, f[N];
int a[N], b[N], sum[N];

int find(int x)
{
    if (x == f[x])
        return x;
    return f[x] = find(f[x]);
}

void check(int x, int y)
{
    int xx = find(x), yy = find(y);
    if (xx != yy)
    {
        f[xx] = find(yy);
    }
}

void solve()
{
    cin >> n;
    int flag = 1;
    for (int i = 1; i <= n; i++)
        f[i] = i, sum[i] = 0;
    map<int, int> mp;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i] >> b[i];
        if (a[i] == b[i])
            flag = 0;
        mp[a[i]]++;
        mp[b[i]]++;
    }
    for (int i = 1; i <= n; i++)
    {
        if (mp[i] >= 3)
        {
            flag = 0;
            break;
        }
        check(a[i], b[i]);
    }
    if (!flag)
    {
        cout << "NO" << endl;
        return;
    }
    for (int i = 1; i <= n; i++)
    {
        f[i] = find(f[i]);
        sum[f[i]]++;
    }
    for (int i = 1; i <= n; i++)
        if (sum[i] & 1)
        {
            cout << "NO\n";
            return;
        }
    cout << "YES" << '\n';
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
复制代码

 

F - Equate Multisets

题意

不用太听题目的话,它说不让你动a你就真不动a吗。

我们可以先把所有的a[i]和b[i]都一直除2,直到它们成为奇数为止,然后我们就可以去看b能不能去匹配a。我们可以用哈希表来把a中数的出现次数都记录下来,然后再用b去匹配,如果b[i]没有被哈希表记录,我们就继续/2,直到被哈希表被记录过,如果b[i]为0了还是没出现过,那说明这个b[i]不可能变成任意一个a,直接就是no了。如果能找到匹配的,则哈希表中这个数的出现次数–。能全部匹配成功就是yes。

为什么可以这么想呢,比如说a[i]=10,我们想得到它,那么这个b[i]就一定可以通过/2操作变成5,因为我们通过*2操作是不可能得到5这个奇数的,那么就只能是通过/2操作,如果通过/2操作得不到这个5,那这个b[i]一定无法匹配这个a[i]。为了方便我们不一个个匹配,我们直接把他们都变成最简的奇数,然后再由b[i]继续/2来看看能不能得到a[i]中的数。

思路

不用太听题目的话,它说不让你动a你就真不动a吗。

我们可以先把所有的a[i]和b[i]都一直除2,直到它们成为奇数为止,然后我们就可以去看b能不能去匹配a。我们可以用哈希表来把a中数的出现次数都记录下来,然后再用b去匹配,如果b[i]没有被哈希表记录,我们就继续/2,直到被哈希表被记录过,如果b[i]为0了还是没出现过,那说明这个b[i]不可能变成任意一个a,直接就是no了。如果能找到匹配的,则哈希表中这个数的出现次数–。能全部匹配成功就是yes。

为什么可以这么想呢,比如说a[i]=10,我们想得到它,那么这个b[i]就一定可以通过/2操作变成5,因为我们通过*2操作是不可能得到5这个奇数的,那么就只能是通过/2操作,如果通过/2操作得不到这个5,那这个b[i]一定无法匹配这个a[i]。为了方便我们不一个个匹配,我们直接把他们都变成最简的奇数,然后再由b[i]继续/2来看看能不能得到a[i]中的数。

 

复制代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl "\n"
const ll N = 2e5 + 233, mod = 1e9 + 7;
map<int, int> ma;
int s[N];
void solve()
{
    ma.clear();
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        int a;
        cin >> a;
        while (a % 2 == 0)
            a /= 2;
        ma[a]++;
    }
    for (int i = 1; i <= n; i++)
        cin >> s[i];
    for (int i = 1; i <= n; i++)
    {
        int a = s[i];
        while (a % 2 == 0)
            a /= 2;
        bool flag = 0;
        while (a > 0)
        {
            if (ma[a] == 0)
                a /= 2;
            else
            {
                ma[a]--;
                flag = 1;
                break;
            }
        }
        if (!flag)
        {
            cout << "NO\n";
            return;
        }
    }

    cout << "YES\n";
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
复制代码

 

posted @   黎_lyh  阅读(93)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示