欧拉路 / 回路 / 有向/ 无向 / 字典顺序

博客探讨了欧拉路在无向图和有向图中的条件,包括欧拉回路和欧拉路的定义,并提供了判断欧拉路存在的算法。此外,还介绍了如何按字典顺序输出有向图的欧拉路,涉及并查集和递归等数据结构与算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/**
    欧拉路就是一笔画问题,同时会衍生出好多问题
    比如:单词接龙,就是给一堆英文单词,问是否能让其首尾相接
    排成一列
    这样可将每个单词看成一条边,首尾字母看成点,求是否存在一
    条欧拉路

    一、无向图
    欧拉回路:每个顶点入度都是偶数
    欧拉路:所有点度数为偶数或者只有两个点度数为奇数
    二、有向图
    欧拉回路:每个点入度等于出度
    欧拉路:每个点入度等于出度或只有一个点入度比出度小1(从这个
    点出发),只有一个点出度比入度小1(从这个点结束),其它点
    入度等于出度。

    例子:按字典顺序输出有向图的欧拉路

    struct node {
        int u, v;
        int vis;  //是否访问过,初始为0
        int w;    //边权,w可以使任意类型,当然也可以使字符串
    }edge[eM];    //存边

    int n, m;     //表示点的个数,边得个数

    int in[nM], out[nM], root[nM], path[nM];
    //入度,出度,并查集用,记录路径

    //初始化,除root,其余都赋值为零
    for (int i=0; i<=n; i++)
        root[i] = i;   //root 初始化,并查集用

    //添边操作
    int k = 0; //k的个数最后赋给m
    void addEdge(int u, int v, int w) {
        edge[k].u = u;
        edge[k].v = v;
        edge[k++].w = w;
        in[v]++;        //入度
        out[u]++;       //出度
        //下面时并查用,判断图联通
        int x = find(u);
        int y = find(v);
        if (x != y)
            root[x] = y;
    }

    //find 函数,并查集经常用的,这个题主要判断图联通,
    int find(int x) {
        return root[x] == x ? : root[x] = find(root[x]);
    }

    //现在判断是否存在欧拉路,这里以欧拉路为例,其它都比较简单

    int start = judge();    //定义一个起点
    //judge() 函数
    int judge() {
        int num=0, ns=0, ne=0, s=-1;
        for (int i=1; i<=n; i++) {
            if (find(i) == i)   num++;  //根节点个数
            if (in[i] != out[i]) {
                if (in[i]-out[i] == 1)
                    ne++;   //  结束点,入度比出度大一
                else if (out[i]-in[i] == 1) {
                    ns++;
                    s = i;  // 起始点
                }
                else
                    return -1;  //返回 -1 代表不存在
            }
        }
        if (num != 1)   return -1;
        if (!((ns==1&&ne==1) || (ns==0&&ne==0)))
            return -1;   //不符合存在欧拉路的条件
        if (s == -1)     //如果s == -1 则随便返回一个起点
            return 1;    //这里返回 1
        return s;
    }

    //如果start == -1 则不存在欧拉路
    //如需按字典输出,则对边按权值优先排序
    sort();

    //递归输出欧拉路
    k = 0;
    eular(start);
    //eular() 函数
    void eular(int u) {
        for (int i=0; i<m; i++) {
            if (!edge[i].vis && edge[i]==u) {
            //无向图条件 (edge[i].u==u || edge[i].v==u)
                edge[i].vis = true;
                eular(edge[i].v);
            //无向图的话 eular(edge[i].v+edge[i].u - u);
                path[k++] = i;
            }
        }
    }

    //从 k-1 -> 0 输出路径

    欧拉路判断最为复杂,其它三种尤其无向图,judge() 函数
    比较容易写,这就不写了,根据上面它所对应的规则

    图算法都不在于本身,而在于把问题转换成图算法

    只要经过足够的练习,都是浮云,这个比赛考智商么,那些牛人
    之所以能很快把题做出来,只有一个可能,这个题型他以前见过,
    大量练习才是王道。

    POJ 2337 1041
*/

//这几天在看新版福尔摩斯,超级精彩  http://tv.sohu.com/20110218/n279411831.shtml

收藏于 2012-01-18
来自于百度空间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值