求欧拉回路的路径 dfs的一种新运用

思路为:
      求欧拉回路的思路:
  循环的找到出发点。从某个节点开始,然后查出一个从这个出发回到这个点的环路径。这种方法保证每个边都被遍历。如果有某个点的边没有被遍历就让这个点为起点,这条边为起始边,把它和当前的环衔接上。这样直至所有的边都被遍历。这样,整个图就被连接到一起了。
  具体步骤:
  1。如果此时与该点无相连的点,那么就加入路径中
  2。如果该点有相连的点,那就列一张表,遍历这些点,直到没有相连的点。
  3。处理当前的点,删除走过的这条边,并在其相邻的点上进行同样的操作,并把删除的点加入到路径中去。
  4。这个其实是个递归过程。
注意record中的点的排列是输出的到序,因此,如果要输出欧拉路径,需要将record倒过来输出。



int num = 0;  // 标记输出队列
int ol[1000]  // 存储欧拉路径
int bz[1000]  //存储每个点的度数 (无向图)
void oula(int x)
{
      if(bz[x] == 0)    ol[num++] = x;
      else
      {
      for(int v = 1; v <= n;  v++)
      {
            if(grap[x][v])
            {
                  grap[x][v] -= 1;
                  grap[v][x] -= 1;
                  bz[x] -= 1;
                  bz[v] -= 1;
                  oula(v);
            }
      }
      ol[num++] = x;
      }
}

第二种方法:
//求欧拉回路的路径 , 要求经过所有边 , 然后再回到起点

//这是dfs来求路径 , 但是时间复杂度只有O(n + m) ,这是一种dfs的运用 , 记录节点在dfs之后再记录
//对于欧拉回路来说 , 任何一个点都能是起点 , 因此 , 我们任选一个点 , 作为起点 ,
//如果搜到不能继续搜索 , 并且当前路径没有包含所有边 , 那么一定某个地方的还有几个环没有遍历 ,
//所以我们进行反向记录 , 每次都是在搜索完了之后在记录 , 那么对于没有被搜索到的环 , 我们就能回去//继续搜索 , 并且由于点是搜索完了才记录 , 所以就类似于把终点当做起点
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;

int grap[100][100];
int n , m;
int pre[100][100];
int edge[110] , t;

void dfs(int u)
{
      for(int i = 1; i <= n; i++)
      {
            if(grap[u][i] == 1 && pre[u][i] == 0)
            {
                  pre[u][i] = pre[i][u] = 1;
                  dfs(i);
                  edge[t++] = i;
//每个点的度数都是偶数 , 所以每个点至少连有两条边
            }
      }
}

int main()
{
      memset(grap , 0 , sizeof(grap));
      memset(grap , 0 , sizeof(grap));
      int i , j , x , y;
      t = 0;
      cin>>n>>m;
      for(i = 1; i <= m; i++)
      {
            scanf("%d %d" , &x , &y);
            grap[x][y] = grap[y][x] = 1;
      }
      //edge[t++] = 1;
      dfs(1);
      edge[t++] = 1;
      for(i = 0; i < t-1; i++)
            cout<<edge[i]<<"  "<<edge[i+1]<<endl;
      return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值