首页 > 其他分享 >2020-2021 ICPC NERC (NEERC), North-Western Russia Regional Contest (Northern Subregionals) E(离散化+欧拉回

2020-2021 ICPC NERC (NEERC), North-Western Russia Regional Contest (Northern Subregionals) E(离散化+欧拉回

时间:2024-04-30 14:11:45浏览次数:20  
标签:std din North cur Northern Contest int auto mp

E - Easy Compare-and-Set

题意

给定n个条件,如果存在一个合法序列使得这n个判断条件成立,则输出Yes和这个合法序列,否则输出No。

分析

首先可以发现对于\(w_i = 0\)的操作我们可以在处理完\(w_i = 1\)的操作之后讨论一下即可。
发现\(a_i\)和\(b_i\)很大需要对其进行离散化操作。离散化后可以将\(a_i\)和\(b_i\)看成点,即一条从a走向b的有向边。将所有的\(w_i = 1\)的边连接起来之后,则可以发现题目等价于问以c为起点能否恰好经过每条边一次,最后跑一边欧拉回路记录路径即可。
对于\(w_i = 0\)的情况我们可以先将所有\(a_i \neq c\)的操作先用掉,对于\(a_i = c\)的操作在跑图时插在第2的点中间即可。
最后注意判断无解情况,具体看代码实现。

代码实现

#include <bits/stdc++.h>
int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    int n, c;
    std::cin >> n >> c;
    std::unordered_map<int, int> mp;
    std::vector<int> w(n);
    std::vector<std::array<int, 3>> edges(n);
    int cur = 0;
    mp[c] = cur++;
    c = mp[c];
    for (int i = 0; i < n; ++i) {
        int a, b;
        std::cin >> a >> b >> w[i];
        if (!mp.count(a)) mp[a] = cur++;
        if (!mp.count(b)) mp[b] = cur++;
        a = mp[a], b = mp[b];
        edges[i] = {a, b, w[i]};
    }
    std::vector<int> din(cur), dout(cur);
    std::vector<std::vector<std::pair<int, int>>> g(cur);
    std::set<int> dot;
    for (int i = 0; i < n; ++i) {
        auto [a, b, e] = edges[i];
        if (e == 1) {
            g[a].emplace_back(b, i);
            dot.emplace(a), dot.emplace(b);
            din[b] += 1, dout[a] += 1;
        }
    }
    for (int num = 0; auto x : dot) if (din[x] != dout[x]) {
        if (din[x] < dout[x]) {
            if (x != c || dout[x] - din[x] > 1) {
                std::cout << "No" << '\n';
                return 0;
            }
        } else {
            num += 1;
            if (num > 1 || din[x] - dout[x] > 1) {
                std::cout << "No" << '\n';
                return 0;
            }
        }
    }
    std::vector<bool> use(n);    
    std::vector<int> path, ans1, ans2;
    for (int i = 0; i < n; ++i) {
        auto [a, b, _] = edges[i];
        if (w[i] == 0 && a != c) {
            use[i] = true;
            ans1.emplace_back(i);
        } else if (w[i] == 0) {
            use[i] = true;
            ans2.emplace_back(i);
        }
    }
    auto dfs = [&](auto &&self, int u) ->void {
        while(size(g[u])) {
            auto [v, e] = g[u].rbegin()[0];
            use[e] = true;
            g[u].pop_back();
            self(self, v);
            path.emplace_back(e);
        }
    };
    dfs(dfs, c);
    if (((int)size(path) == 0 && size(ans2)) || std::count(use.begin(), use.end(), true) != n || (cur == 1 && std::count(w.begin(), w.end(), 1) != n)) {
        std::cout << "No" << '\n';
    } else {
        std::cout << "Yes" << '\n';
        for (int i = 0; i < (int)size(ans1); ++i) {
            std::cout << ans1[i] + 1 << " ";
        }
        int pos = size(path);
        for (int i = 0; i < (int)size(path); ++i) { 
            if (edges[path.rbegin()[i]][0] == c) {
                std::cout << path.rbegin()[i] + 1 << " \n"[i == (int)size(path) - 1];
            } else {
                pos = i;
                break;
            }
        }
        for (int i = 0; i < (int)size(ans2); ++i) {
            std::cout << ans2[i] + 1 << " ";
        }
        for (int i = pos; i < (int)size(path); ++i) {
            std::cout << path.rbegin()[i] + 1 << " \n"[i == (int)size(path) - 1];
        }
    }
}
Thanks:

最后感谢学弟提供的hack样例,不然实在是没想到为什么wa6。
╲(。◕‿◕。)╱

标签:std,din,North,cur,Northern,Contest,int,auto,mp
From: https://www.cnblogs.com/sleeeeeping/p/18167933

相关文章

  • AtCoder Beginner Contest 351
    B-SpottheDifference难度:⭐题目大意给定两个矩阵,找不同解题思路数据很小,暴力就行;神秘代码#include<bits/stdc++.h>#defineintunsignedlonglong#defineIOSios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#defineendl'\n'usingnamespa......
  • AtCoder Beginner Contest 208 E
    E-DigitProducts点击查看代码map<int,int>f[20];voidsolve(){intn,k;cin>>n>>k;autos=to_string(n);intm=s.size();function<int(int,int,int,int)>dfs=[&](inti,intlimit,intis_num,intmul)->int{if(i......
  • 2018-2019 ACM-ICPC, China Multi-Provincial Collegiate Programming Contest
    A.MaximumElementInAStack按照题目模拟就好,栈内的最大值可以维护单调栈解决。#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;usingui32=unsignedint;ui32SA,SB,SC;ui32rng61(){SA^=SA<<16;SA^=SA>>5;SA^......
  • AtCoder Beginner Contest 351 E - Jump Distance Sum 切比雪夫距离与曼哈顿距离的转
    先说知识点。曼哈顿距离:横纵坐标距离差的绝对值的和,即|X1-X2|+|Y1-Y2|,离(0,0)点曼哈顿距离为1的点形成的是一个旋转45度后的正方形切比雪夫距离:横纵坐标距离差的绝对值的最大值,即max(|X1-X2|,|Y1-Y2|),离(0,0)点切比雪夫距离为1的点形成的是一个不旋转的正方形曼哈......
  • The 2nd GUAT Collegiate Programming Contest (Round 1)
    第二届GUAT大学生程序设计大赛第一场题解(A-M)前言比赛的内容主要包括计算机科学的常用算法,基本的计算理论,(如:离散数学,具体数学,组合数学基础),数据结构基础,程序设计语言(规定是C/C++或者是Java、Python)。在本项比赛中考察学生的不仅仅是能够完成指定任务的程序,更要求在完成程序的功......
  • The 2018 ICPC Asia Qingdao Regional Programming Contest (The 1st Universal Cup,
    Preface久违地VP一场,虽然打的挺唐但勉强写出了8题前中期EFB三开三卡属实有点难受,而且B题这个套路大合集我和徐神两个人写了快200行也占用了一定机时但好在后面把卡住的题慢慢都写出来了,然后最后40min冲刺L题成功比较可惜的是I这个开场看的题没有再细想一步,感觉想到在线段树上D......
  • The 2023 ICPC Asia Jinan Regional Contest
    目录写在前面DIAG写在最后写在前面比赛地址:https://codeforces.com/gym/104901。以下按个人向难度排序。SUA的题确实牛逼,把我这种只会套路的沙比狠狠腐乳了。D签到。直接枚举\([L,\min(R,L+10)]\)检查即可。///*By:Luckyblock*/#include<bits/stdc++.h>#defi......
  • The 2022 ICPC Asia Xian Regional Contest / ICPC 西安 2022 (ABDHJKL)
    本文搬运自本人的知乎文章。https://zhuanlan.zhihu.com/p/588162564好久没有在补题之后写题解的习惯了。但是最近感觉有些题目的思路即使在题目通过后仍然难以理清,因此觉得需要写些东西帮助自己整理思路,另外也方便以后翻看积累到的技巧。J.StrangeSum题目链接Problem-J......
  • 2022 China Collegiate Programming Contest (CCPC) Mianyang | 2022 CCPC 绵阳(MAED
    搬运自本人知乎文章。https://zhuanlan.zhihu.com/p/588646549M.Rock-Paper-ScissorsPyramid题目链接Problem-M-Codeforces题意有一个长度为\(n\)的石头剪刀布序列,每个元素是RPS(石头、布、剪刀)中的一个,我们需要用这个序列构造一个三角,三角的底层为这个序列,第\(i(......
  • The 2022 ICPC Asia Xian Regional Contest
    The2022ICPCAsiaXianRegionalContestJ.StrangeSum题意:给定n个数,选定最多不超过两个数字的和的最大值思路:签到voidsolve(){lln;cin>>n;vector<ll>a(n+1);for(inti=1;i<=n;i++)cin>>a[i];llans=0;sort(a.begin()......