码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-02-12 12:58:41      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:iostream   cstring   排列   欧拉图   基本   顶点   set   连通   没有   

 

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

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\n",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\n",t[i]);
50     }
51     return 0;
52 }

 

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

标签:iostream   cstring   排列   欧拉图   基本   顶点   set   连通   没有   

原文地址:https://www.cnblogs.com/very-beginning/p/12298453.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!