首页 > 其他分享 >题解:[ARC188C] Honest or Liar or Confused

题解:[ARC188C] Honest or Liar or Confused

时间:2024-11-24 15:11:36浏览次数:7  
标签:村民 Liar int 题解 dsu Honest 题面 诚实 撒谎

乍一看以为是 3-SAT 不可做,动动脑子发现是 2-SAT(

鉴于本题解书写时洛谷题面暂无中文翻译,为避免可能的歧义或困惑,先对本题解中的译法进行约定:

  • 英文题面中“honest villager”或日文题面中“正直者”译为“诚实村民”。
  • 英文题面中“liar”或日文题面中“嘘つき”译为“撒谎村民”。
  • 英文题面中“confused”或日文题面中“混乱している”译为“糊涂的”。
  • 英文题面中“not confused”或日文题面中“混乱していない”译为“清醒的”。
  • 英文题面中“testimony”或日文题面中“証言”译为“证言”。

设 \(P_i\) 表示第 \(i\) 位村民是否是撒谎村民,\(Q_i\) 表示第 \(i\) 位村民是否是糊涂的。根据题意列出证言的真值表:

\(A\) 身份 \(P_A\) \(A\) 状态 \(Q_A\) \(B\) 身份 \(P_B\) \(C\) 结果 \(C\)
诚实村民 \(0\) 清醒的 \(0\) 诚实村民 \(0\) 诚实村民 \(0\)
诚实村民 \(0\) 清醒的 \(0\) 撒谎村民 \(1\) 撒谎村民 \(1\)
诚实村民 \(0\) 糊涂的 \(1\) 诚实村民 \(0\) 撒谎村民 \(1\)
诚实村民 \(0\) 糊涂的 \(1\) 撒谎村民 \(1\) 诚实村民 \(0\)
撒谎村民 \(1\) 清醒的 \(0\) 诚实村民 \(0\) 撒谎村民 \(1\)
撒谎村民 \(1\) 清醒的 \(0\) 撒谎村民 \(1\) 诚实村民 \(0\)
撒谎村民 \(1\) 糊涂的 \(1\) 诚实村民 \(0\) 诚实村民 \(0\)
撒谎村民 \(1\) 糊涂的 \(1\) 撒谎村民 \(1\) 撒谎村民 \(1\)

容易观察到证言 \((A,B,C)\) 实际上限制了 \(P_A\oplus Q_A\oplus P_B=C\)。

注意到,一位村民是否是撒谎村民和她是否清醒是无关的,并且上式中 \(P_A\) 和 \(Q_A\) 总是绑定在一起,因此不难想到设 \(R_i=P_i\oplus Q_i\)。证言 \((A,B,C)\) 的限制转化为 \(R_A\oplus P_B=C\),是经典的 2-XOR-SAT 问题。使用扩展域并查集求解出 \(P_i\) 和 \(R_i\) 的一组解(或判定无解),再根据 \(Q_i=P_i\oplus R_i\) 求得并输出 \(Q_i\) 即可。

题目要求构造出一组解(而非判定是否有解),构造的过程比较容易想不清楚写错,赛时直接爽吃五发罚时。

核心代码:

//By: OIer rui_er
#define rep(x, y, z) for(int x = (y); x <= (z); ++x)
#define per(x, y, z) for(int x = (y); x >= (z); --x)

const int N = 8e5 + 5;

int n, m, ans[N];

struct Dsu {
    int fa[N];
    void init(int x) {rep(i, 1, x) fa[i] = i;}
    int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
    bool same(int x, int y) {return find(x) == find(y);}
    bool merge(int x, int y) {
        if(same(x, y)) return false;
        x = find(x); y = find(y);
        fa[x] = y;
        return true;
    }
}dsu;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> n >> m;
    dsu.init(4 * n);
    rep(i, 1, m) {
        int u, v, w;
        cin >> u >> v >> w;
        if(w == 0) {
            dsu.merge(u + 2 * n, v);
            dsu.merge(u + 2 * n + n, v + n);
        }
        else {
            dsu.merge(u + 2 * n, v + n);
            dsu.merge(u + 2 * n + n, v);
        }
    }
    rep(i, 1, n) {
        if(dsu.same(i, i + n)) {
            cout << "-1" << endl;
            return 0;
        }
        if(dsu.same(i + 2 * n, i + 2 * n + n)) {
            cout << "-1" << endl;
            return 0;
        }
    }
    // rep(i, 1, n) cout << dsu.find(i) << " " << dsu.find(i + n) << " " << dsu.find(i + 2 * n) << " " << dsu.find(i + 3 * n) << endl;
    rep(i, 1, n) {
        if(dsu.same(i, i + 2 * n)) cout << 0;
        else if(dsu.same(i, i + 2 * n + n)) cout << 1;
        else {
            dsu.merge(i + 2 * n, i);
            dsu.merge(i + 2 * n + n, i + n);
            cout << 0;
        }
    }
    cout << endl;
    return 0;
}

标签:村民,Liar,int,题解,dsu,Honest,题面,诚实,撒谎
From: https://www.cnblogs.com/ruierqwq/p/18565841/arc188c

相关文章

  • CF1328题解
    CF1328A简单题,我们用\(b-a%b\)的余数即可,注意特判\(a%b==0\)即可CF1328B细节蛮多的,我们可以发现最终个数可以写成\(1+2+3+\dots+(p-1)+p+g\)最后\(n-p\)就是第一个b的位置,\(n-g\)就是第二个b的位置,可以推式子然后\(O(n)\)求但是我选择二分查找g,然后注意一下细节......
  • CF 1638 题解
    CF1638题解AReverse贪心的想,找到第一个\(a_i\not=i\)的位置,然后操作\([i,pos_{a_i}]\)这个区间即可.BOddSwapSort由于只能交换奇数和偶数,奇数偶数内部的相对位置不能改变,因此合法的充要条件是奇数之间已经有序,偶数亦然.CInversionGraph由于有效树边只......
  • [CodeForces] CF21 题解
    这次不放难度了。因为我懒A.JabberID【题目大意】一个地址由<username>@<hostname>[/resource]组成,其中[/resource]可以被省略。<username>字段允许大写、小写字母,数字、下划线,其长度应在\(1\)到\(16\)之间。<hostname>字段允许用.来分隔。每一段的要求同<u......
  • LeetCode题解:29.两数相除【Python题解超详细,位运算、二分查找法、递归法】,知识拓展:位
    题目描述        给你两个整数,被除数 dividend 和除数 divisor。将两数相除,要求 不使用 乘法、除法和取余运算。整数除法应该向零截断,也就是截去(truncate)其小数部分。例如,8.345 将被截断为 8 ,-2.7335 将被截断至 -2 。返回被除数 dividend 除以除数 div......
  • [ARC188C] Honest or Liar or Confused
    扩展域并查集+带权并查集。题意中给的是骗子与否和糊涂与否,似乎有多个二元关系。观察结果:如果一个人不糊涂,那么\(C=0\)代表他们同是诚实的或者都是骗子;\(C=1\)代表他们的诚实与否不同。这时我们就可以不在意这个人是否诚实了,我们就去关系人与人之间的相对关系。若这个人......
  • 【题解】CF2031
    Atag:签到题注意到定住一个值后,左边的值全都得改,右边的值也全都得改注意到,定住的越多,需要改的就越少所以开桶记一下哪个值最多就行Btag:诈骗诈骗签到题读完题容易产生naive结论:当且仅当错位的两个地方相邻可以修复,其余情况全部无法修复感觉真不了一点,于是找三个数ABC......
  • 读数据质量管理:数据可靠性与数据质量问题解决之道13数据沿袭
    1. 数据沿袭1.1. MyDoom的病毒1.2. 现在,许多团队甚至整个公司都在使用数据,这要求数据管理的方式要更便于合作,同时也更不容许发生错误1.3. 从采用dbt和ApacheAirflow等开源工具来实现数据转换和编排,到使用Snowflake和Databricks等云端数据仓库和数据湖1.4. 数据仪表板和......
  • ybtoj 高效进阶题解索引
    密码:sunxuhetai2009--------------------云落的分割线--------------------基础算法第1章-递推算法第2章-贪心算法第3章-二分算法第4章-深搜算法第5章-广搜算法已完结--------------------云落的分割线--------------------图论第1章-并查集第4章-强连......
  • 攻防世界 web(新手模式)题解
    1.view_source题目描述:X老师让小宁同学查看一个网页的源代码,但小宁同学发现鼠标右键好像不管用了。根据题目提示直接F12查看源代码,发现答案就在源代码里2.get_post题目描述:X老师告诉小宁同学HTTP通常使用两种请求方法,你知道是哪两种吗?根据提示,我们需要用GET方式提......
  • 题解:AT_abc381_c [ABC381C] 11/22 Substring
    显然这个“11/22Substring”是以那个“/”为中心对称的。鉴于一个这样的字符串只能有一个“/”,而题目又要求最长,所以确定了“/”就能确定一个满足要求的子串。那思路就很简单了,只有两步:找到所有的“/”两边同时寻找相应的子串。别的,除了判断一下越界之外,就不用管了。......