• 骑马修栅栏


    嘟嘟嘟

    今天学了个欧拉回路~

    理解起来感觉不是很难,证明竟然也看懂了。

    首先,得认识这么几个名词:

    1.欧拉路径:图中存在一条从s到t的路径,使这条路径经过了所有的边,且每条边之经过一次。简单来说就是这张图可以一笔画出来.

    2.欧拉回路:就是欧拉回路中s == t。

    3.欧拉图:存在欧拉回路的图。

    4.半欧拉图:存在欧拉路径但是不存在欧拉回路的图。

    然后,有这么几个结论:

    1.欧拉图一定是连通的。(废话)

    2.欧拉图中每一个点的度数都是偶数。

      因为对于每一个点,一定是从一条边进入,从一条边离开,而且这些边都不重,所以每一条边的度数都为偶数。

    3.半欧拉图中只有两个点的度数为奇数,其余点的度数为偶数,而且这两个点一个是起点,一个是终点。

      起点的入度比出度少1,终点的入度比出度多1.

    4.有向图为欧拉图,当且仅当所有点的入度等于出度。

    然后怎么找欧拉回路:

    以无向图为例:伪代码

     1 void dfs(int x)
     2 {
     3    对于从x出发的所有边(x, y)
     4       如果(x, y)没被访问
     5          标记(x, y),(y, x)为已访问
     6             dfs(y)
     7    把x放入栈
     8 }
     9 
    10 int main()
    11    倒序输出栈中所有元素

    有向图类似。

    考虑这道题,有个非常烦人的一点:输出字典序最小的。

    然后我就想到了这么个方法:用邻接矩阵存图。但这样只有在n比较小的时候才能过……

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<stack>
     9 #include<queue>
    10 #include<vector>
    11 using namespace std;
    12 #define enter puts("")
    13 #define space putchar(' ')
    14 #define Mem(a, x) memset(a, x, sizeof(a))
    15 #define rg register
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const db eps = 1e-8;
    20 const int maxn = 505;
    21 inline ll read()
    22 {
    23   ll ans = 0;
    24   char ch = getchar(), las = ' ';
    25   while(!isdigit(ch)) las = ch, ch = getchar();
    26   while(isdigit(ch)) ans = ans * 10 + ch - '0', ch = getchar();
    27   if(las == '-') ans = -ans;
    28   return ans;
    29 }
    30 inline void write(ll x)
    31 {
    32   if(x < 0) putchar('-'), x = -x;
    33   if(x >= 10) write(x / 10);
    34   putchar(x % 10 + '0');
    35 }
    36 
    37 int m, n = -1;
    38 int G[maxn][maxn], du[maxn];
    39 
    40 stack<int> st;
    41 void euler(int now)
    42 {
    43   for(int i = 1; i <= n; ++i)
    44     if(G[now][i])
    45       {
    46     G[now][i]--; G[i][now]--;
    47     euler(i);
    48       }
    49     st.push(now);
    50 }
    51 
    52 int main()
    53 {
    54   m = read();
    55   for(int i = 1; i <= m; ++i)
    56     {
    57       int x = read(), y = read();
    58       n = max(n, max(x, y));
    59       G[x][y]++; G[y][x]++;
    60       du[x]++; du[y]++;
    61     }
    62   bool flg = 1;
    63   for(int i = 1; i <= n && flg; ++i) if(du[i] & 1) {euler(i); flg = 0;}
    64   if(flg) euler(1);
    65   while(!st.empty()) {write(st.top()); enter; st.pop();}
    66   return 0;
    67 }
    View Code
  • 相关阅读:
    (译)构建Async同步基元,Part 3 AsyncCountdownEvent
    (译)构建Async同步基元,Part 5 AsyncSemaphore
    SICP学习笔记(P3P17)
    关于汇编语言寄存器和指令操作的整理
    VS2010和IE8是怎样让"Ctrl+鼠标滚轮的上下操作"实现改变字体或页面大小的
    "六度空间"的应用——找出两个陌生人之间的关系(二)
    关于QQ一些功能的实现(二)
    用Socket做一个局域网聊天工具
    SICP学习笔记(P27P28)
    算法练习 (二)
  • 原文地址:https://www.cnblogs.com/mrclr/p/9762223.html
Copyright © 2020-2023  润新知