zoukankan      html  css  js  c++  java
  • 骑马修栅栏

    嘟嘟嘟

    今天学了个欧拉回路~

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

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

    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
  • 相关阅读:
    BZOJ1527 : [POI2005]Pun-point
    2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016)
    2016-2017 ACM-ICPC Northwestern European Regional Programming Contest (NWERC 2016)
    NAIPC-2016
    BZOJ2498 : Xavier is Learning to Count
    ACM ICPC Vietnam National Second Round
    XVI Open Cup named after E.V. Pankratiev. GP of Ukraine
    XVI Open Cup named after E.V. Pankratiev. GP of Peterhof
    HDU5509 : Pattern String
    BZOJ4583 : 购物
  • 原文地址:https://www.cnblogs.com/mrclr/p/9762223.html
Copyright © 2011-2022 走看看