USACO算法系列十四——fence

     题目:http://www.nocow.cn/index.php/Translate:USACO/fence

    看完这道题目的第一想法就是,遍历所有的边,而且每一条边的经过次数只能一次。是离散数学里面的图论的欧拉通路问题,在这里充分体现了数学的重要性。

    定理:无向图G有欧拉通路的充分必要条件是G为连通图,并且G仅有两个奇度结点或者无奇度结点。
           (1)当G是仅有两个奇度结点的连通图时,G的欧拉通路必以此两个结点为端点。
           (2)当G是无奇度结点的连通图时,G必有欧拉回路。

    因此第一个点,要么是最小的度数为奇数的点(如果存在),否则为是下标最小的点。

    我的想法是采用深度遍历的回溯方法,如果不能一次遍历完所有的边,则回退到上一个节点,直到搜索到结果为止,代码如下:

   

    可惜的是,时间一直都是超时的,通不过去。

    看了USACO的提示,他也是采用深度遍历的方法,然后将结果逆序保存打印。但是这个深度遍历跟我的那个方法有着本质的区别,他的深度遍历是遍历边,而我的深度遍历是深度搜索,时间复杂度不在一个数量级上。很让我奇怪的是,为什么简简单单的一次深度遍历边,然后逆序保存节点就可以找出欧拉通路呢?

    举个例子:

    正确的欧拉通路顺序是红色的,但是按节点下标的深度遍历的顺序是蓝色方式。很显然如果从方向来看的话,二者的结果肯定是不同的。

   

    我们先看一下代码入下:

    按照程序的执行思路跑一遍,可以得到如下步骤:

    find(1):

           map[1][2] = 1;

           find(2)

                map[2][3] = 1;

                find(3)

                      map[3][4]=1;

                      find(4)

                            map[4][2]=1;

                            find(2) //此时所有的map[2][i] = 0

                                  记录2

                                   return;

                             所有map[4][i]=0

                             记录4

                              return

                      map[3][i] =0

                      记录3

                      return;

                所有map[2][i]=0

                记录2

                return

           map[1][5] = 1;

           find(5)

                 map[5][6] = 1

                 find(6)

                      map[6][1] = 1;

                      find(1);

                            ALL map[1][i]=0;

                            记录1

                             return

                      记录6

                      return

            记录5

            return

         记录1

          return;

    逆序打印结果是1 5 6 1 2 3 4 2,就是正确答案。

    本来我也想不明白其中的缘由,但是如果把问题理解为实际上我们就是寻找一个点序列,使得按照这个点序列遍历边,能经过每一条边,并且只有一次。根据欧拉通路的从要条件,我们可以很明确的得到第一个点(起点)S。那么我们要确定的是下一个欧拉通路的点P,是与起点连接的点中的哪一个?那我们可以想一下,哪一个点是下一个欧拉点P呢?就是沿着S P然后经过深度遍历,能够将所有的边都遍历到的点就是欧拉点,就是经过SP往下深度遍历以后,所有MAP【i】【j】=0。

    运行结果如下:

   

   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值