USACO Riding The Fences 与欧拉路径问题

简单的看,图的路径算法可以分两类:

  1. 可达性寻问题:找到一条满足某种条件的路径,如图的连通性问题(简单路径算法),欧拉路径,汉密顿路径等等;
  2. 含权图的最优化问题:如点对间的最短路径,欧几里德网;

而一切和图有关的算法,几乎都是DFS和BFS,这两家伙乍一看浓眉大眼的。他们所反映的,是计算机中的逻辑性与次序性,世界纷繁复杂,DFS与BFS是探索这些杂乱无章的一种逻辑很清晰、次序性很明显的思维方式。我当时学习图的时候,第一感觉就是乱糟糟恶心的一拖东西堆着,哪像树呢?多好看?为什么好看呢?因为好理解,不断的分叉下去,是吧,规律性很明显!在Wikipedia上找到了两张图,可以很好的说明思维的次序性问题:

USACO Riding The Fences 与欧拉路径问题_第1张图片


好了,回到fence问题上来,欧拉路径的存在性问题已经有了结论了,请见Robert Sedgewick的《Algorithms in C++》,结论是这样的:

  • 对于一个无向图,如果它每个点的度都是偶数,那么它存在一条欧拉回路;
  • 如果有且仅有2个点的度为奇数,那么它存在一条欧拉路;
  • 如果超过2个点的度为奇数,那么它就不存在欧拉路了。

找出欧拉路的方法就是采用DFS的方式,对于当前的点,把所有点从小到大的搜索,找到和它相连的,找到一个之后删除它们之间的连线,并去搜索新的那个点,如果没有找到点和它相连,那么就把这个点加入输出队列。

以上就是这个题的主题思路了,但是仅仅这么做会超时的。前面说:世界纷繁复杂,DFS与BFS是探索这些杂乱无章的一种逻辑很清晰、次序性很明显的思维方式”,现在,有了这个思维的主线条了,接下来就是挖掘其中的细节,也就是剪枝。太多的剪枝我也没发现很多,不过有一点是,前面我们说,找到和它相连的,找到一个之后删除它们之间的连线”,这里是会产生一个问题的,那就是有可能删除了一些要命的边,使得图不连通了:

USACO Riding The Fences 与欧拉路径问题_第2张图片

像上面的,中间那个黄点点挂了,要是左或右还没走完,整个图怎么都走不出一条欧拉回路了。当然图画的有点丑,呵呵~

所以这里又有些考察基础了。Robert的书里有过几个概念:

割点:若一个点删除后(也就是与之相连的边统统去掉),无向图不再连通,那么此点称为割点。
桥:若一条边断去后,无向图不再连通,那么此边称为桥。桥有一个很好的性质,就是DFS一个无向图,那么这个过程必定要经过桥。
块:没有割点的无向图称为2-连通分支,也称作块。

现在应该比较清楚了,也就是说,在进行DFS搜索前,可以先用FloodFill灌水算法判断一下图的连通性,FloodFill算是OIer菜谱上的算法了吧,所以还是基础啊。。。

BTW,FloodFill不一定就是递归的,下面的代码中用的就是一个循环。

  1. /*
  2. ID:fairyroad
  3. LANG:C++
  4. TASK:fence
  5. */
  6. #include <fstream>
  7. #include <vector>
  8. #include <cstring>
  9. using  namespace std ;
  10.  
  11. ifstream fin ( "fence.in" ) ;
  12. ofstream fout ( "fence.out" ) ;
  13.  
  14. const  int MAX  =  505 ;
  15. int edge [MAX ] [MAX ] ;
  16. int nodeCnt [MAX ] ;
  17. bool visited [MAX ] ;
  18. int F ;
  19.  
  20. vector < int > ans ;
  21.  
  22. bool floodFill ( int node )
  23. {
  24.      memset (visited,  0sizeof (visited ) ) ;
  25.     visited [node ]  =  true ;
  26.  
  27.     vector < int > Q ;
  28.     Q. push_back (node ) ;
  29.  
  30.      while ( !Q. empty ( ) )
  31.      {
  32.         node  = Q. back ( ) ;
  33.         Q. pop_back ( ) ;
  34.          for  ( int i  =  0 ; i  < MAX ;  ++i )
  35.          {
  36.              if (edge [node ] [i ]  &&  !visited [i ] )
  37.              {
  38.                 Q. push_back (i ) ;
  39.                 visited [i ]  =  true ;
  40.              }
  41.          }
  42.      }
  43.  
  44.      for  ( int i  =  1 ; i  < MAX ;  ++i )
  45.      {
  46.          if  ( !visited [i ]  && nodeCnt [i ] )
  47.          {
  48.              return  false ;
  49.          }
  50.      }
  51.  
  52.      return  true ;
  53. }
  54.  
  55. bool dfs ( int curr )
  56. {
  57.      if ( ( int )ans. size ( )  == F + 1 )
  58.      {
  59.          for ( size_t i  =  0 ; i  < ans. size ( ) ;  ++i )
  60.             fout  << ans [i ]  << endl ;
  61.          //exit(0);
  62.          return  true ;
  63.      }
  64.  
  65.      if ( !floodFill (curr ) )
  66.          return  false ;
  67.  
  68.      for ( int i  =  1 ; i  < MAX ;  ++i )
  69.      {
  70.          if (edge [curr ] [i ] )
  71.          {
  72.             ans. push_back (i ) ;
  73.              --edge [curr ] [i ] ;  --edge [i ] [curr ] ;
  74.              --nodeCnt [curr ] ;  --nodeCnt [i ] ;
  75.  
  76.              if (dfs (i ) )
  77.                  return  true ;
  78.  
  79.             ans. pop_back ( ) ;
  80.              ++edge [curr ] [i ] ;  ++edge [i ] [curr ] ;
  81.              ++nodeCnt [curr ] ;  ++nodeCnt [i ] ;
  82.          }
  83.      }
  84.  
  85.      return  false ;
  86. }
  87.  
  88. int main ( )
  89. {
  90.     fin  >> F ;
  91.      int i, v1, v2 ;
  92.      for (=  0 ; i  < F ;  ++i )
  93.      {
  94.         fin  >> v1  >> v2 ;
  95.          ++edge [v1 ] [v2 ] ;  ++edge [v2 ] [v1 ] ;
  96.          ++nodeCnt [v1 ] ;  ++nodeCnt [v2 ] ;
  97.      }
  98.  
  99.      int start  =  - 1, oddNode  =  0 ;
  100.      for ( int i  =  0 ; i  < MAX ;  ++i )
  101.      {
  102.          if (nodeCnt [i ]  & 0x1u )
  103.          {
  104.              ++oddNode ;
  105.              if (start  ==  - 1 ) start  = i ;
  106.          }
  107.      }
  108.  
  109.      if (oddNode  ! =  2 )  // 题目保证了有解
  110.         start  =  1 ;
  111.  
  112.     ans. push_back (start ) ;
  113.     dfs (start ) ;
  114.  
  115.      return  0 ;
  116. }

USACO Riding The Fences 与欧拉路径问题_第3张图片


你可能感兴趣的:(c,优化,算法)