欧拉回路--P2731 骑马修栅栏 Riding the Fences

Posted very-beginning

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了欧拉回路--P2731 骑马修栅栏 Riding the Fences相关的知识,希望对你有一定的参考价值。

 

实在懒得复制题干了 *传送

1.定义

*如果图G(有向图或者无向图)中所有边一次仅且一次行遍所有顶点的通路称作欧拉通路。
*如果图G中所有边一次仅且一次行遍所有顶点的回路称作欧拉回路。
*具有欧拉回路的图称为欧拉图(简称E图)。具有欧拉通路但不具有欧拉回路的图称为半欧拉图。

2. 定理及推论

无向图G存在欧拉通路的充要条件是:

1) 当G是仅有两个奇度结点的连通图时,G的欧拉通路必以此两个结点为端点。
2) 当G是无奇度结点的连通图时,G必有欧拉回路。

有向图D存在欧拉通路的充要条件是:

推论2:
1) 当D除出、入度之差为1,-1的两个顶点之外,其余顶点的出度与入度都相等时,D的有向欧拉通路必以出、入度之差为1的顶点作为始点,以出、入度之差为-1的顶点作为终点。
2) 当D的所有顶点的出、入度都相等时,D中存在有向欧拉回路

求解:

A.  DFS搜索求解欧拉回路

基本思路:利用欧拉定理判断出一个图存在欧拉回路或欧拉通路后,选择一个正确的起始顶点,用DFS算法遍历所有的边(每一条边只遍历一次),遇到走不通就回退。在搜索前进方向上将遍历过的边按顺序记录下来。这组边的排列就组成了一条欧拉通路或回路。

 1 #include<cstdio>
 2 #include<stdio.h>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define MAX 2010
 6 using namespace std;
 7 int maps[MAX][MAX];
 8 int in[MAX];
 9 int t[MAX];
10 int flag;
11 int k;
12 int Max,Min;
13 int DFS(int x)
14 {
15     int i;
16     for(i=Min;i<=Max;i++)
17     {
18         if(maps[x][i])///从任意一个与它相连的点出发
19         {
20             maps[x][i]--;///删去遍历完的边
21             maps[i][x]--;
22             DFS(i);
23         }
24     }
25     t[++k]=x;///记录路径,因为是递归所有倒着记
26 }
27 int main()
28 {
29     int n,i,x,y;
30     Max=-9999;
31     Min=9999;
32     flag=0;
33     scanf("%d",&n);
34     for(i=1;i<=n;i++)
35     {
36         scanf("%d%d",&x,&y);
37         maps[x][y]++;
38         maps[y][x]++;
39         Max=max(x,max(y,Max));
40         Min=min(x,min(y,Min));
41         in[x]++;
42         in[y]++;
43     }
44     for(i=Min;i<=Max;i++)
45     {
46         if(in[i]%2)///存在奇度点,说明是欧拉通路
47         {
48             flag=1;
49             DFS(i);
50             break;
51         }
52     }
53     if(!flag)///全为偶度点,从标号最小的开始找
54     {
55         DFS(Min);
56     }
57     for(i=k;i>=1;i--)
58     {
59         printf("%d
",t[i]);
60     }
61     return 0;
62 }

B.  Fleury(佛罗莱)算法

 1 #include <cstdlib>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 int ans[200];
 8 int top;
 9 int N,M;
10 int mp[200][200];
11 void dfs(int x)
12 {
13     int i;
14     top++;
15     ans[top]=x;
16     for (i=1; i<=N; i++)
17     {
18         if(mp[x][i]>0)
19         {
20             mp[x][i]=mp[i][x]=0;///删除此边
21             dfs(i);
22             break;
23         }
24     }
25 }
26 
27 void fleury(int x)
28 {
29     int brige,i;
30     top=1;
31     ans[top]=x;///将起点放入Euler路径中
32     while(top>=0)
33     {
34         brige=0;
35         for (i=1; i<=N; i++) /// 试图搜索一条边不是割边(桥)
36         {
37             if(mp[ans[top]][i]>0)///存在一条可以扩展的边
38             {
39                 brige=1;
40                 break;
41             }
42         }
43         if (!brige)/// 如果没有点可以扩展,输出并出栈
44         {
45             printf("%d ", ans[top]);
46             top--;
47         }
48         else     /// 否则继续搜索欧拉路径
49         {
50             top--;///为了回溯
51             dfs(ans[top+1]);
52         }
53     }
54 }
55 
56 int main()
57 {
58     int x,y,deg,num,start,i,j;
59     scanf("%d%d",&N,&M);
60     memset(mp,0,sizeof (mp));
61     for(i=1;i<=M; i++)
62     {
63         scanf("%d%d",&x,&y);
64         mp[x][y]=1;
65         mp[y][x]=1;
66     }
67     num=0;
68     start=1;///这里初始化为1
69     for(i=1; i<=N; i++)
70     {
71         deg=0;
72         for(j=1; j<=N; j++)
73         {
74             deg+=mp[i][j];
75         }
76         if(deg%2==1)///奇度顶点
77         {
78             start=i;
79             num++;
80         }
81     }
82     if(num==0||num==2)
83     {
84         fleury(start);
85     }
86     else
87     {
88         puts("No Euler path");
89     }
90     return 0;
91 }

 那这道题就是一个欧拉回路的板子

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 using namespace std;
 5 int map[10001][10001];//记录两个点之间的路径个数 
 6 int du[10001];//辅助记录奇点 
 7 int t[10001];//记录路径 
 8 int n,x,y,k=0;
 9 int Max=0,Min=1e9;
10 int DFS(int x)
11 {
12     int i;
13     for(i=Min;i<=Max;i++)
14     {
15         if(map[x][i])
16         {
17             map[x][i]--;
18             map[i][x]--;
19             DFS(i);
20         }
21     }
22     t[++k]=x;
23 }
24 int main()
25 {
26     scanf("%d",&n);
27     for(int i=1;i<=n;++i)
28     {
29         scanf("%d%d",&x,&y);
30         map[x][y]++;
31         map[y][x]++;
32         du[x]++;
33         du[y]++; 
34         Max=max(Max,max(x,y));
35         Min=min(Min,min(x,y)); 
36     }
37     int start=1; 
38     for(int i=1;i<=Max;++i)
39     {
40         if(du[i]%2)
41         {
42             start=i;
43             break; 
44         }
45     }
46     DFS(start); 
47     for(int i=k;i>=1;i--)
48     {
49         printf("%d
",t[i]);
50     }
51     return 0;
52 }

 

以上是关于欧拉回路--P2731 骑马修栅栏 Riding the Fences的主要内容,如果未能解决你的问题,请参考以下文章

P2731 骑马修栅栏 Riding the Fences

洛谷 P2731 骑马修栅栏 Riding the Fences

洛谷P2731 骑马修栅栏 Riding the Fences

P2731 骑马修栅栏 Riding the Fences

LG2731 骑马修栅栏 Riding the Fences

luogu P2731 骑马修栅栏 Riding the Fences