zoukankan      html  css  js  c++  java
  • Euleriar Path 入门

    一、前置技能

     >  图的概念

     >  dfs遍历图

     >  stack

     >  一笔画

    二、定义

    看过上面链接 是不是对一笔画产生了兴趣呢?

    (A:没有!)

    好吧……其实通俗来讲 欧拉路径就是OI意义下的一笔画

    也就是 图中经过每条边一次并且仅一次的路径

    欧拉回路就是满足欧拉路径性质的回路

    同时我们定义欧拉图(其实就是一笔画出来的图)

    存在欧拉回路的图称为欧拉图。
    存在欧拉路径但不存在欧拉回路的图称为半欧拉图。

    三、性质与定理

    这种路径很特殊 不一定所有的图都有(比如大部分树)

    规定一个点的度数为过这个点的边数(应该都知道)

    刨去孤立点(没有度数的点)之后(显然,这样做并不会影响图中欧拉回路的存在性。)

      >  Q:先考虑无向图

    发现我们考虑边无法推知下一步的方向 转而考虑点

    然后就可以发现 在欧拉路径中除了起点和终点 进入每个点一次的时候一定会出去一次

    所以除了起点和终点每个点的度数均为偶数

    而欧拉回路中起点和终点重合

    所以 欧拉图满足 每个点的度数为偶数

    半欧拉图满足 仅有两个点的度数为奇数

    那么 每个点度数为偶数的图(>0)一定有欧拉回路吗?

    证明:

    首先 如果图中没有回路 那么一定是一颗树 就一定有度数不是偶数的点(叶子)

    所以一定有回路

    然后比如我们找到了一个回路C

    当我们把这条回路上的边都不计的时候

    由于这是一条回路每一个点的度数减少量也一定是偶数(随手画个环看一下?)

    剩下的图中就一定还有回路 把两个回路拼起来就有新的回路

    最后全拼起来就能遍历所有的边 于是C就变成了欧拉回路

    (欧拉路证明类似)

     >  Q:那么有向图?

    同理 每条边有起点和终点 就把度数变成 入度出度 

    当入度==出度 也就是进入的边数和出去的边数一样的时候 满足是欧拉图

    仅有一个入度为1 仅有一个出度为1的时候 满足是半欧拉图

     > Q:那么混合图?

    (啪!)

    混合图欧拉回路是一个经典网络流问题 放别的地方讲

     >  Q:所以……怎么实现?

    其实刚刚证明的时候就已经说完了最常用的 套圈法 的基本过程

    实现的时候开一个栈存删掉的边(是否惰性删除都行)

    最后沿着栈逆序输出就OK了

    注意欧拉回路没有一定的起点 所以经常要输出字典序最小

    这个时候邻接矩阵就比较方便 当然像某些dalao把链前排序也行

    这里粘一下Code吧

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 #define itn int
     6 #define ms(a,b) memset(a,b,sizeof a)
     7 #define rep(i,a,n) for(int i = a;i <= n;i++)
     8 #define per(i,n,a) for(int i = n;i >= a;i--)
     9 using namespace std;
    10 typedef long long ll;
    11 ll read() {
    12     ll as = 0,fu = 1;
    13     char c = getchar();
    14     while(c < '0' || c > '9') {
    15         if(c == '-') fu = -1;
    16         c = getchar();
    17     }
    18     while(c >= '0' && c <= '9') {
    19         as = as * 10 + c - '0';
    20         c = getchar();
    21     }
    22     return as * fu;
    23 }
    24 const int N = 550;
    25 //head
    26 int n,m;
    27 int a[N][N];
    28 int stk[N<<1],top;
    29 void dfs(int x) {
    30     rep(y,1,n) {
    31     if(!a[x][y]) continue;
    32     a[x][y]--,a[y][x]--;
    33     dfs(y);
    34     }
    35     stk[++top] = x;
    36 }
    37 int du[N];
    38 int main() {
    39     m = read();
    40     rep(i,1,m) {
    41     int x = read(),y = read();
    42     n = max(max(x,y),n);
    43     a[x][y]++,a[y][x]++;
    44     du[x]++,du[y]++;
    45     }
    46     bool flag = 1;
    47     rep(i,1,n) 
    48     if(du[i] & 1) {
    49         if(flag) dfs(i);
    50         flag = 0;
    51     }
    52     if(flag) dfs(1);
    53     while(top) printf("%d
    ",stk[top--]);
    54     return 0;
    55 }

    应该是luogu一道绿题吧……

    > 别忘了 总有人在等着你
  • 相关阅读:
    PAT (Advanced Level) 1010. Radix (25)
    PAT (Advanced Level) 1009. Product of Polynomials (25)
    PAT (Advanced Level) 1008. Elevator (20)
    PAT (Advanced Level) 1007. Maximum Subsequence Sum (25)
    PAT (Advanced Level) 1006. Sign In and Sign Out (25)
    PAT (Advanced Level) 1005. Spell It Right (20)
    PAT (Advanced Level) 1004. Counting Leaves (30)
    PAT (Advanced Level) 1001. A+B Format (20)
    PAT (Advanced Level) 1002. A+B for Polynomials (25)
    PAT (Advanced Level) 1003. Emergency (25)
  • 原文地址:https://www.cnblogs.com/yuyanjiaB/p/9764348.html
Copyright © 2011-2022 走看看