判别一个无向图中某两点之间是否存在一条长度为k的简单路径

问题简述:在一个无向图中,如何判别两点间是否存在一条长度为K的简单路径?

算法思想:

为描述方便,设起始顶点为 src,目的顶点为 dst。

1)当 k == 0 时,如果此时  src == dst,则存在。否则不存在。

2)当 k >= 1时,当前点为 src,依次遍历与 src 相邻的顶点 vi,将问题递归为求起始顶点为 vi, 目的节点为 dst,长度为 k-1 的简单路径是否存在。


在算法的实现中,需要注意的是避免死循环问题。

1)避免从 vi 到 vj 后,又从 vj 返回到 vi,造成循环。

2)再者,假设 src 到 dst 的路径经过 src 的相邻节点 vj,虽然 vj 到 dst 可能不存在 k-1 的简单路径,但是可能存在其他长度的路径,这就需要增加一个辅助数组,用以标识 以 vj 为起点,到dst 长度为 k-1 的路径有没有尝试过,如果尝试过了就跳过,这样当求长度 k 为其它值的时候可以再次以 vj 为起点。


代码如下

#include<iostream>
using std::cout;
using std::endl;

#include<stack>
using std::stack;

#include<vector>
using std::vector;

#include<cstdlib>
using std::atoi;

#include<cassert>

template<size_t N>
bool HasSimpleKPath(int src, int dst, int k, int (&gm)[N][N], stack<int>& trace, vector<vector<bool> >& aux)
{
    assert(k >= 0);
    
    if(k == 0){
        return src == dst;
    }

    if(!aux[src][k]){ // src has not visited it's children by k length.
        aux[src][k] = true;
        for(size_t i = 0; i < N; ++i){
            if(gm[src][i] > 0){
                int old = gm[src][i];
                gm[src][i] = 0;
                gm[i][src] = 0;

                bool has = HasSimpleKPath(i, dst, k - 1, gm, trace, aux);
                gm[src][i] = old;
                gm[i][src] = old;
                if(has){
                    trace.push(src);
                    return true;
                }
            }
        }
    }

    return false;
}

测试代码如下:

int main(int argc, char* argv[]){
    const int sz = 7;
    int gm[sz][sz] = {
        {0, 0, 0, 1, 1, 0, 0},
        {0, 0, 1, 0, 1, 0, 0},
        {0, 1, 0, 1, 0, 0, 0},
        {1, 0, 1, 0, 0, 1, 1},
        {1, 1, 0, 0, 0, 0, 0},
        {0, 0, 0, 1, 0, 0, 0},
        {0, 0, 0, 1, 0, 0, 0}
    };

    if(argc != 4){
        std::cerr << "usage: " << argv[0] << " src dst k" << endl;
        return 1;
    
    }

    int src, dst, k;
    stack<int> trace;

    src = atoi(argv[1]);
    dst = atoi(argv[2]);
    k = atoi(argv[3]);
    vector<vector<bool> > aux(sz, vector<bool>(k + 1, false));
    if(HasSimpleKPath(src, dst, k, gm, trace, aux)){
        while(!trace.empty()){
            cout << 'v' << trace.top() << "-->";
            trace.pop();
        }
        cout << 'v' << dst << endl;
    } 
    else{
        cout << "Not found!" << endl;
    }
    return 0;
}

测试程序中的邻接矩阵所表示的图如下图所示 :


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值