• [欧拉路]CF1152E Neko and Flashback


    1152E - Neko and Flashback

    题意:对于长为n的序列c和长为n - 1的排列p,我们可以按照如下方法得到长为n - 1的序列a,b,a',b'。

    ai = min(ci, ci+1),bi = max(ci, ci+1)

    a'i = ap[i],b'i = bp[i]

    现在给定a'和b',求一个合法的c或者无解。

    解:仔细分析性质,发现在a和b中,c除了开头和结尾会出现1次之外,每个数都会出现两次,且相邻。

    我们可以把c的开头找出来,然后根据开头确定c2,然后确定c3...最后到cn

    注意到这些数可能有重复的,于是我们要试图在中间插入一段。我一开始想的是链表后来发现很难写...

    仔细分析,如果把a'和b'的每个位置当成边,数字当成点,就是求欧拉路。然后就没了......

    关于欧拉路:就暴力DFS,把每条边都访问一次。回溯的时候把这条边入栈/把y入栈。

      1 #include <bits/stdc++.h>
      2 
      3 const int N = 200010;
      4 
      5 struct Edge {
      6     int nex, v, id, pre;
      7 }edge[N << 1]; int tp = 1;
      8 
      9 int X[N], xx, a[N], b[N], cnt[N], e[N], stk[N], top, deg[N];
     10 bool vis[N];
     11 
     12 inline void erase(int x, int i) {
     13     int nex = edge[i].nex, pre = edge[i].pre;
     14     if(e[x] == i && !nex) {
     15         e[x] = 0;
     16     }
     17     else if(e[x] == i) {
     18         e[x] = nex;
     19         edge[nex].pre = 0;
     20         return;
     21     }
     22     else if(!nex) {
     23         edge[pre].nex = 0;
     24     }
     25     else {
     26         edge[nex].pre = pre;
     27         edge[pre].nex = nex;
     28     }
     29     edge[i].nex = edge[i].pre = 0;
     30     return;
     31 }
     32 
     33 inline void add(int x, int y, int z) {
     34     edge[++tp].v = y;
     35     edge[tp].id = z;
     36     edge[tp].nex = e[x];
     37     edge[e[x]].pre = tp;
     38     e[x] = tp;
     39     return;
     40 }
     41 
     42 void DFS(int x) {
     43     for(int i = e[x]; i; i = edge[i].nex) {
     44         erase(x, i);
     45         int y = edge[i].v;
     46         if(vis[edge[i].id]) {
     47             continue;
     48         }
     49         vis[edge[i].id] = 1;
     50         DFS(y);
     51         stk[++top] = y;
     52     }
     53     return;
     54 }
     55 
     56 int main() {
     57     
     58     int n;
     59     scanf("%d", &n);
     60     for(int i = 1; i < n; i++) {
     61         scanf("%d", &a[i]);
     62         X[++xx] = a[i];
     63     }
     64     for(int j = 1; j < n; j++) {
     65         scanf("%d", &b[j]);
     66         X[++xx] = b[j];
     67         if(b[j] < a[j]) {
     68             puts("-1");
     69             return 0;
     70         }
     71     }
     72     
     73     std::sort(X + 1, X + xx + 1);
     74     xx = std::unique(X + 1, X + xx + 1) - X - 1;
     75     for(int i = 1; i < n; i++) {
     76         a[i] = std::lower_bound(X + 1, X + xx + 1, a[i]) - X;
     77         b[i] = std::lower_bound(X + 1, X + xx + 1, b[i]) - X;
     78         add(a[i], b[i], i);
     79         add(b[i], a[i], i);
     80         deg[a[i]]++;
     81         deg[b[i]]++;
     82     }
     83     int s = 0, pos = 1;
     84     for(int i = 1; i <= xx; i++) {
     85         if(deg[i] & 1) {
     86             s++;
     87             pos = i;
     88         }
     89     }
     90     if(s != 0 && s != 2) {
     91         puts("-1");
     92         return 0;
     93     }
     94     
     95     DFS(pos);
     96     stk[++top] = pos;
     97     if(top != n) {
     98         puts("-1");
     99         return 0;
    100     }
    101     for(int i = top; i >= 1; i--) {
    102         printf("%d ", X[stk[i]]);
    103     }
    104     
    105     return 0;
    106 }
    AC代码

    注意复杂度,删边......

     1 #include <bits/stdc++.h>
     2 
     3 const int N = 200010;
     4 
     5 struct Edge {
     6     int nex, v, id;
     7 }edge[N << 1]; int tp = 1;
     8 
     9 int X[N], xx, a[N], b[N], cnt[N], e[N], stk[N], top, deg[N];
    10 bool vis[N];
    11 
    12 inline void add(int x, int y, int z) {
    13     edge[++tp].v = y;
    14     edge[tp].id = z;
    15     edge[tp].nex = e[x];
    16     e[x] = tp;
    17     return;
    18 }
    19 
    20 void DFS(int x) {
    21     for(int i = e[x]; i; i = e[x]) {
    22         e[x] = edge[i].nex;
    23         int y = edge[i].v;
    24         if(vis[edge[i].id]) {
    25             continue;
    26         }
    27         vis[edge[i].id] = 1;
    28         DFS(y);
    29         stk[++top] = y;
    30     }
    31     return;
    32 }
    33 
    34 int main() {
    35     
    36     int n;
    37     scanf("%d", &n);
    38     for(int i = 1; i < n; i++) {
    39         scanf("%d", &a[i]);
    40         X[++xx] = a[i];
    41     }
    42     for(int j = 1; j < n; j++) {
    43         scanf("%d", &b[j]);
    44         X[++xx] = b[j];
    45         if(b[j] < a[j]) {
    46             puts("-1");
    47             return 0;
    48         }
    49     }
    50     
    51     std::sort(X + 1, X + xx + 1);
    52     xx = std::unique(X + 1, X + xx + 1) - X - 1;
    53     for(int i = 1; i < n; i++) {
    54         a[i] = std::lower_bound(X + 1, X + xx + 1, a[i]) - X;
    55         b[i] = std::lower_bound(X + 1, X + xx + 1, b[i]) - X;
    56         add(a[i], b[i], i);
    57         add(b[i], a[i], i);
    58         deg[a[i]]++;
    59         deg[b[i]]++;
    60     }
    61     int s = 0, pos = 1;
    62     for(int i = 1; i <= xx; i++) {
    63         if(deg[i] & 1) {
    64             s++;
    65             pos = i;
    66         }
    67     }
    68     if(s != 0 && s != 2) {
    69         puts("-1");
    70         return 0;
    71     }
    72     
    73     DFS(pos);
    74     stk[++top] = pos;
    75     if(top != n) {
    76         puts("-1");
    77         return 0;
    78     }
    79     for(int i = top; i >= 1; i--) {
    80         printf("%d ", X[stk[i]]);
    81     }
    82     
    83     return 0;
    84 }
    另一种删边方式
  • 相关阅读:
    axis2 WebService的发布与调用
    sql语句having子句用法,很多时候你曾忘掉
    linux下tomcat开机自启动
    框架使用的技术主要是SpringMVC 在此基础上进行扩展
    SpringMVC整合Mongodb开发 架构搭建
    解决Linux下3T硬盘分区只有2T(2199G)可用
    ubuntu cp(copy) command
    Linux如何根据UUID自动挂载磁盘分区
    python exec和eval
    在OpenERP报表中使用selection 类型字段
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10958711.html
Copyright © 2020-2023  润新知