欧拉回路--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