zoukankan      html  css  js  c++  java
  • LG 题解 CF1152E Neko and Flashback

    更好的阅读体验?

    Description

    题目传送

    题目翻译好像有点问题,应该改为,

    [b_i = min {a_i, a_{i+1} } ]

    [c_i = max {a_i, a_{i+1} } ]

    Solution

    先说做法,欧拉路径。

    如果不知道什么是欧拉路径,可以去看一下这个模板题

    其实这个做法通过观察样例就能看出来。

    其实 (p) 序列没啥用,唯一的用处就是让你可以打乱这个 (b,c) 序列,实现过程中不需要考虑它。

    考虑欧拉回路正确性,对于一对 (b_i, c_i),一定分别对应着 (a_i,a_{i+1}) 的两个值,可以看做是两个点连边,而 (b_{i+1})(c_{i+1}) 又能将 (a_{i+1})(a_{i+2}) 连接。最后整个 (a) 序列就是一条由每一对 (b_i,c_i) 连起来的合法的欧拉路径。

    对了,虽然 (b,c) 序列的值域是 (10^9),但离散化一下就好了。

    剩下的就是判断不合法(无解)情况:

    • (b_i > c_i),这个通过样例二就能看出来,并且 (min {a_i, a_{i+1} } > max {a_i, a_{i+1} }) 这本来就是不合法的。
    • 还有就是 (b,c) 序列没有构成欧拉路径,这个可以根据度数为奇数的点的数量来判断,只有 (0)(2) 的情况是合法的。
    • 当然图可能不连通,所以我们只 dfs 一遍,如果栈中的元素不等于 (n),也是无解的。

    这里建议用 vector 存边,并且用数组 (now) 来记录当前点遍历到了那条边,下次经过的时候可以跳过前面已经遍历过的边,达到优化复杂度的效果,以防被卡到 (O(m^2))

    注意一对 (b_i,c_i) 所连的边是双向边,vector 本身是不方便同时对一对边标记的,不过我们可以对每条边多存一个信息 (id) (表示它是第几条边)来解决。

    Code

    /*
    Work by: Suzt_ilymics
    Problem: 不知名屑题
    Knowledge: 垃圾算法
    Time: O(能过)
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define LL long long
    #define orz cout<<"lkp AK IOI!"<<endl
    
    using namespace std;
    const int MAXN = 3e5+5;
    const int INF = 1e9+7;
    const int mod = 1e9+7;
    
    struct node {
        int v, id;
    };
    
    int n;
    int b[MAXN], c[MAXN];
    int date[MAXN], date_num = 0, Cnt = 0;
    vector<node> e[MAXN];
    int now[MAXN], du[MAXN];
    int stc[MAXN], sc = 0;
    bool vis[MAXN];
    
    int read(){
        int s = 0, f = 0;
        char ch = getchar();
        while(!isdigit(ch))  f |= (ch == '-'), ch = getchar();
        while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
        return f ? -s : s;
    }
    
    void dfs(int u) {
        for(int M = e[u].size(); now[u] < M; ) {
            node v = e[u][now[u]++];
            if(vis[v.id]) continue;
            vis[v.id] = true;
            dfs(v.v);
        }
        stc[++sc] = u;
    }
    
    int main()
    {
        n = read();
        for(int i = 1; i < n; ++i) date[++date_num] = b[i] = read();
        for(int i = 1; i < n; ++i) date[++date_num] = c[i] = read();
        for(int i = 1; i < n; ++i) {
            if(b[i] > c[i]) {
                puts("-1");
                return 0;
            }
        }
        sort(date + 1, date + date_num + 1), date[0] = -INF;
        for(int i = 1; i <= date_num; ++i) if(date[i] != date[i - 1]) date[++Cnt] = date[i];
        for(int i = 1; i < n; ++i) {
            b[i] = lower_bound(date + 1, date + Cnt + 1, b[i]) - date;
            c[i] = lower_bound(date + 1, date + Cnt + 1, c[i]) - date;
            e[b[i]].push_back((node){c[i],i}), du[c[i]]++;
            e[c[i]].push_back((node){b[i],i}), du[b[i]]++;
        }
        int js = 0;
        for(int i = 1; i <= Cnt; ++i) if(du[i]&1) js++;
        if(js != 0 && js != 2) {
            puts("-1");
            return 0;
        }
        bool flag = false;
        for(int i = 1; i <= Cnt; ++i) {
            if(du[i] & 1) {
                dfs(i);
                flag = true;
                break;
            }
        }
        if(!flag) dfs(1);
        if(sc != n) puts("-1");
        else while(sc) printf("%d ", date[stc[sc--]]);
        return 0;
    }
    
  • 相关阅读:
    php原生PHPExcel插件导表(附表格合并,加粗居中及加边框换行操作)
    VMware虚拟机基于contos 7 搭建lnmp环境全过程
    菜鸟学git的基本命令及常见错误
    为什么要写blog????
    JavaScript高级程序设计--函数小记
    jsapi微信支付
    Javascript模式小记(一)
    图片的增删查
    图形的滚动及颜色区域的拉移
    网页中的宽与高
  • 原文地址:https://www.cnblogs.com/Silymtics/p/solution-CF1152E.html
Copyright © 2011-2022 走看看