ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[AcWing 258] 石头剪刀布

2022-08-16 21:35:02  阅读:148  来源: 互联网

标签:return 裁判 int same merge 258 剪刀 find AcWing


image
image
image

带扩展域的并查集


点击查看代码
#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 1e6 + 10;

int n, m;
int p[N];

struct Node
{
    int a, b;
    char op;
} s[N];

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

void merge(int a, int b)
{
    int pa = find(a), pb = find(b);
    p[pa] = pb;
}

bool same(int a, int b)
{
    return find(a) == find(b);
}

bool check(int a, int b, char c)
{
    if (c == '=') {
        if (same(a, b + n) || same(a + n, b))
            return false;
        merge(a, b);
        merge(a + n, b + n);
        merge(a + n + n, b + n + n);
    }
    else if (c == '>') {
        if (same(a, b) || same(a + n, b))
            return false;
        merge(a, b + n);
        merge(a + n, b + n + n);
        merge(a + n + n, b);
    }
    else {
        if (same(a, b) || same(a, b + n))
            return false;
        merge(a + n, b);
        merge(a + n + n, b + n);
        merge(a, b + n + n);
    }
    return true;
}

void solve()
{
    while (cin >> n >> m) {
        for (int i = 1; i <= m; i ++) {
            int a, b;
            char op;
            cin >> a >> op >> b;
            s[i] = {a, b, op};
        }
        // 记录裁判的个数
        int cnt = 0;
        // 记录裁判的编号
        int res = 0;
        // 记录得到裁判信息的行号
        int the_line = 0;
        // 假设编号为 t 的人是裁判
        for (int t = 0; t < n; t ++) {
            // 每次都要将集合初始化
            for (int i = 0; i < 3 * n; i ++)
                p[i] = i;
            bool is_ok = true;
            for (int i = 1; i <= m; i ++) {
                auto& [a, b, op] = s[i];
                // 将裁判跳过
                if (a == t || b == t)
                    continue;
                // 检查是否合法,合法则合并集合,不会进入if中
                if (!check(a, b, op)) {
                    // 不合法才会进入
                    is_ok = false;
                    // 其他人不是裁判的最大轮数
                    if (the_line <= i)
                        the_line = i;
                    break;
                }
            }
            if (is_ok) {
                res = t;
                cnt ++;
            }
        }
        if (!cnt)
            printf("Impossible\n");
        else if (cnt > 1)
            printf("Can not determine\n");
        else
            printf("Player %d can be determined to be the judge after %d lines\n", res, the_line);
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    solve();

    return 0;
}

  1. 判断裁判的思路
    先假设一定存在裁判,枚举把每个人当作裁判,然后将包含他的数据跳过,判断其他数据是否会推出矛盾,如果没有矛盾,则说明这个人可能是裁判,就把 \(cnt + 1\),考虑以下几种情况:
    ① 如果没有裁判,
    ② 如果只有一位裁判,那么只有当枚举到把他当作裁判时,其他数据才会没有矛盾,\(cnt + 1\) 只会执行一次,最终 \(cnt = 1\)
    ③ 如果有裁判,但是不能确定哪个是裁判,那么有多个人选,把他当作裁判时,其他数据没有矛盾,\(cnt + 1\) 会执行超过一次,\(cnt > 1\)
  2. 扩展域
    对于 \(a\) 号小朋友,\(a\) 代表该小朋友出的是石头,\(a + n\) 代表该小朋友出的是剪刀,\(a + n + n\) 代表该小朋友出的是布
  3. 最早的找到裁判的时间 \(\Leftrightarrow\) 判断出除他以外的人都不是裁判的时间 \(\Leftrightarrow\) 判断出其他人不是裁判的时间的最大值

标签:return,裁判,int,same,merge,258,剪刀,find,AcWing
来源: https://www.cnblogs.com/wKingYu/p/16593028.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有