一笔画问题

一笔画问题

  如果一个图存在一笔画,则一笔画的路径叫做欧拉路,如果最后又回到起点,那这个路径叫做欧拉回路。

  我们定义奇点是指跟这个点相连的边数目有奇数个的点。对于能够一笔画的图,我们有以下两个定理。

定理1:存在欧拉路的条件:图是连通的,有且只有2个奇点。

定理2:存在欧拉回路的条件:图是连通的,有0个奇点。

两个定理的正确性是显而易见的,既然每条边都要经过一次,那么对于欧拉路,除了起点和终点外,每个点如果进入了一次,显然一定要出去一次,显然是偶点。对于欧拉回路,每个点进入和出去次数一定都是相等的,显然没有奇点。

一笔画性质:

■⒈凡是由偶点组成的连通图,一定可以一笔画成。画时可以把任一偶点为起点,最后一定能以这个点为终点画完此图。

■⒉凡是只有两个奇点的连通图(其余都为偶点),一定可以一笔画成。画时必须把一个奇点为起点,另一个奇点为终点。

■⒊其他情况的图都不能一笔画出。(奇点数除以二便可算出此图需几笔画成。)

  求欧拉路的算法很简单,使用深度优先遍历即可。

根据一笔画的两个定理,如果寻找欧拉回路,对任意一个点执行深度优先遍历;找欧拉路,则对一个奇点执行DFS,时间复杂度为O(m+n),m为边数,n是点数。

l       以下是寻找一个图的欧拉路的算法实现:

l       样例输入:第一行n,m,有n个点,m条边,以下m行描述每条边连接的两点。

l           5 5

l           1 2

l           2 3

l           3 4

l           4 5

l           5 1

l       样例输出:欧拉路或欧拉回路

l           1 5 4 3 2 1

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 int a[1000][1000];
 7 int du[1000];
 8 int sh;
 9 int n,m;
10 int tot=0;
11 int ans[1000];
12 int q,h;
13 void search(int A)
14 {
15     for(int j=1;j<=n;j++)
16      {
17          if(a[A][j]==1)
18           {
19               a[A][j]=0;
20               a[j][A]=0;
21             search(j);
22          }
23      }
24      //tot++;
25      ans[++tot]=A;
26 }
27 int main()
28 {
29     memset(a,0,sizeof(a));
30     cin>>n>>m;
31     for(int i=1;i<=m;i++)
32      {
33          cin>>q>>h;
34          a[q][h]=1;
35          a[h][q]=1;
36          du[h]++;
37          du[q]++;
38      }
39      sh=1;
40      for(int i=1;i<=n;i++)
41       {
42           if(du[i]%2==1)
43            {
44                sh=i;
45            }
46       }
47       search(sh);
48       for(int i=1;i<=tot;i++)
49        {
50            cout<<ans[i]<<" ";
51        }
52 }

 

posted @ 2017-04-08 21:29  ioioioioioio  阅读(1393)  评论(0编辑  收藏  举报