【东华大学oj】找出从指定结点出发且长度为m的所有简单路径

找出从指定结点出发且长度为m的所有简单路径

作者: 冯向阳

时间限制: 1s

章节: 课程设计

问题描述

在使用图的邻接表ADT的基础上,设计一个算法,按照深度优先搜索的思想找出从指定结点出发且长度为m的所有简单路径。并将此算法加入到邻接表ADT中,在邻接表ADT中提供一个公有的成员函数FindPath(start, m)。

提示:

(1)这个问题相当于从指定结点开始深度优先遍历,而且遍历的深度正好为m。为此,在遍历时需要记住遍历的深度,当深度达到m时,就不需要递归了。此时需要输出这条路径,因此在遍历的过程中还需要记住整条路径。

(2)由于深度优先遍历是用递归实现的,所以FindPath函数最好也设计两个。一个是共有的FindPath函数,供用户使用(外壳);另一个是私有的FindPath函数,实现递归的遍历。公有的FingPath函数调用私有的FindPath函数找出这些路径。

(3)在调用递归的FindPath函数前,外壳函数还需要做一些辅助工作:

1)要找的是长度为m的简单路径,因此路径上不能有相同的结点,于是定义了一个数组visited记录结点是否在路径上。

2)当路径长度等于m时要输出这条路径,于是定义了一个数组stack保存这条路径。每访问一个结点,都要把结点记录在stack中。

3)递归的FindPath函数有6个参数。第1个参数是遍历的起点的序号;第2个参数是要求的路径长度;第3个参数是符合要求的路径数目;第4个参数是当前路径中的结点数,当前路径的长度是结点数减1;第5个参数是visited数组,记录结点是否在路径上;第6个参数是一个用于记录路径上结点序号的数组,作用和栈类似。

4)调用FindPath函数时要指出从哪一个结点出发,而递归的FingPath函数的参数是起点的序号。递归的FindPath函数首先将起点放入这条路径,并标记这个结点已被访问,然后判断路径长度是否是m。如果长度已达到m,则输出这条路径,并将最后一个结点从路径上删除,返回上一层调用,检查是否还有其它的途径;否则逐个检查起点的后继结点。如果该后继结点没有被访问过,则对该结点调用递归的FindPath函数继续寻找。在所有的后继都检查后,表示这条路径处理完毕。将起始结点从这条路径上删除,返回上一层调用。

参考函数原型:

(1)//找出从指定结点出发且长度为m的所有简单路径(外壳部分) 

template<class TypeOfVer, class TypeOfEdge>

void adjlist_graph<TypeOfVer, TypeOfEdge>::FindPath(int start, int m);

(2)//找出从指定结点出发且长度为m的所有简单路径(递归部分) 

template<class TypeOfVer, class TypeOfEdge>

void adjlist_graph<TypeOfVer, TypeOfEdge>::FindPath(int start, int m, int &count, int top, int visited[], int stack[]);

输入说明

第一行:图的类型

第二行:结点数

第三行:结点集

第四行:边数

第五行:边集

第六行:起点start

第七行:路径长度m

输出说明

第一行:顶点集

第二行:邻接表

空行

如无符合要求的路径:输出 0

否则: 路径输出(一条路径占一行)

           路径数目

#include <iostream>
#include <string>
#include <queue>
#include <vector>
using namespace std;

template<class TypeOfEdge>
struct edgeNode
{
    size_t data;
    TypeOfEdge weight;
    edgeNode<TypeOfEdge>* next;

    edgeNode(const size_t& d, const TypeOfEdge& w, edgeNode<TypeOfEdge>* ptr = nullptr)
    {
        data = d;
        weight = w;
        next = ptr;
    }
};

template<class TypeOfVer, class TypeOfEdge>
struct verNode
{
    TypeOfVer ver;
    edgeNode<TypeOfEdge>* head;

    verNode(edgeNode<TypeOfEdge>* h = nullptr)
    {
        head = h;
    }
};

template <class TypeOfVer, class TypeOfEdge>
class adjlist_graph
{
private:
    int Vers; // Number of vertices
    verNode<TypeOfVer, TypeOfEdge>* verList;
    string GraphKind;

    void BFS_Util(queue<int>& q, vector<bool>& visited)
    {
        if (q.empty())
            return;

        int u = q.front();
        cout << verList[u].ver;

        q.pop();

        edgeNode<TypeOfEdge>* curr = verList[u].head;
        while (curr != nullptr)
        {
            size_t v = curr->data;
            if (!visited[v])
            {
                q.push(v);
                visited[v] = true;
            }
            curr = curr->next;
        }

        if (!q.empty())
        {
            cout << "->";
            BFS_Util(q, visited);
        }
    }

public:
    int Get_InDegree(int u, string& kd)
    {
        if (u < 0 || u >= Vers || kd == "UDG" || kd == "UDN")
            return -1;

        int inDegree = 0;
        for (int i = 0; i < Vers; ++i)
        {
            edgeNode<TypeOfEdge>* curr = verList[i].head;
            while (curr != nullptr)
            {
                if (curr->data == u)
                    ++inDegree;
                curr = curr->next;
            }
        }
        return inDegree;
    }

    void FindPath(int start, int m, int& count);
    void FindPath(int start, int m, int& count, int top, int visited[], int stack[]);
    void BFS_Traverse(int u)
    {
        vector<bool> visited(Vers, false);
        queue<int> q;
        q.push(u);
        visited[u] = true;

        BFS_Util(q, visited);
    }

    adjlist_graph(const string& kd, int vSize, const TypeOfVer d[]) : Vers(vSize), GraphKind(kd)
    {
        verList = new verNode<TypeOfVer, TypeOfEdge>[Vers];
        for (int i = 0; i < Vers; ++i)
        {
            verList[i].ver = d[i];
        }
    }

    adjlist_graph(const string& kd, int vSize, int eSize, const TypeOfVer d[], int** e) : Vers(vSize), GraphKind(kd)
    {
        verList = new verNode<TypeOfVer, TypeOfEdge>[Vers];
        for (int i = 0; i < Vers; ++i)
        {
            verList[i].ver = d[i];
            verList[i].head = nullptr;
        }

        for (int i = 0; i < eSize; ++i)
        {
            int u = e[i][0];
            int v = e[i][1];
            edgeNode<TypeOfEdge>* newNode = new edgeNode<TypeOfEdge>(v, 0, verList[u].head);
            verList[u].head = newNode;

            newNode = new edgeNode<TypeOfEdge>(u, 0, verList[v].head);
            verList[v].head = newNode;
        }
    }

    adjlist_graph(const string& kd, int vSize, int eSize, const TypeOfVer d[], int** e, const TypeOfEdge w[]) : Vers(vSize), GraphKind(kd)
    {
        verList = new verNode<TypeOfVer, TypeOfEdge>[Vers];
        for (int i = 0; i < Vers; ++i)
        {
            verList[i].ver = d[i];
            verList[i].head = nullptr;
        }

        for (int k = 0; k < eSize; ++k)
        {
            int u = e[k][0];
            int v = e[k][1];
            TypeOfEdge weight = w[k];

            if (GraphKind == "DG" || GraphKind == "DN")
            {
                edgeNode<TypeOfEdge>* newNode = new edgeNode<TypeOfEdge>(v, weight, verList[u].head);
                verList[u].head = newNode;
                 }
            else
            {
                edgeNode<TypeOfEdge>* newNode = new edgeNode<TypeOfEdge>(v, weight, verList[u].head);
                verList[u].head = newNode;

                newNode = new edgeNode<TypeOfEdge>(u, weight, verList[v].head);
                verList[v].head = newNode;
            }
        }
    }

    ~adjlist_graph()
    {
        for (int i = 0; i < Vers; ++i)
        {
            edgeNode<TypeOfEdge>* curr = verList[i].head;
            while (curr != nullptr)
            {
                edgeNode<TypeOfEdge>* temp = curr;
                curr = curr->next;
                delete temp;
            }
        }
        delete[] verList;
    }

    void printAdjList()
    {
        for (int i = 0; i < Vers; ++i)
        {
            cout << verList[i].ver;
            edgeNode<TypeOfEdge>* curr = verList[i].head;
            while (curr != nullptr)
            {
                cout << "->" << curr->data;
                curr = curr->next;
            }
            cout << endl;
        }
    }

    bool PrintMatrix()
    {
        cout << GraphKind << endl;
        for (int i = 0; i < Vers; ++i)
        {
            cout << verList[i].ver;
            if (i != Vers - 1)
                cout << " ";
        }
        cout << endl;
        return true;
    }

    bool GetWeight(int u, int v, TypeOfEdge& w);
};

template<class TypeOfVer, class TypeOfEdge>
bool adjlist_graph<TypeOfVer, TypeOfEdge>::GetWeight(int u, int v, TypeOfEdge& w)
{
    if (u < 0 || u >= Vers || v < 0 || v >= Vers)
         return false;

    edgeNode<TypeOfEdge>* curr = verList[u].head;
    while (curr != nullptr)
    {
        if (curr->data == v)
        {
            w = curr->weight;
            return true;
        }
        curr = curr->next;
    }
    return false;
}

template<class TypeOfVer, class TypeOfEdge>
void adjlist_graph<TypeOfVer, TypeOfEdge>::FindPath(int start, int mm, int& count)
{
    int* visited = new int[Vers];
    int* stack = new int[mm + 1];

    for (int i = 0; i < Vers; ++i) visited[i] = 0;
    FindPath(start, mm, count, 0, visited, stack);
    delete[] visited;
    delete[] stack;
}

template<class TypeOfVer, class TypeOfEdge>
void adjlist_graph<TypeOfVer, TypeOfEdge>::FindPath(int start, int mm, int& count, int top, int visited[], int stack[])
{
    visited[start] = 1;
    stack[top] = start;

    if (top == mm)
    {
        for (int i = 0; i <= top; ++i)
        {
            cout << verList[stack[i]].ver;
            if (i < top)
                cout << "->";
        }
        cout << endl;
        count++;

    }
    else
    {
        for (edgeNode<TypeOfEdge>* p = verList[start].head; p != nullptr; p = p->next)
        {
            if (!visited[p->data])
                FindPath(p->data, mm, count, top + 1, visited, stack);
        }
    }

    visited[start] = 0;
}

int main()
{
    string graphType;
    int n, m, count=0;
    cin >> graphType >> n;

    string* verArr = new string[n];
    for (int i = 0; i < n; ++i)
    {
        cin >> verArr[i];
    }

    cin >> m;
    int** edgeArr = new int* [m];
    for (int i = 0; i < m; ++i)
    {
        edgeArr[i] = new int[2];
        cin >> edgeArr[i][0] >> edgeArr[i][1];
    }

    int* weightArr = new int[m];
    for (int i = 0; i < m; ++i)
    {
        weightArr[i] = 1;
    }
    int start, mm;
    cin >> start >> mm;
    adjlist_graph<string, int> graph(graphType, n, m, verArr, edgeArr, weightArr);

    // 输出顶点集和邻接表
    for (int i = 0; i < n; ++i)
    {
        cout << verArr[i];
        if (i < n - 1) cout << " ";
    }
    cout << endl;
    graph.printAdjList();
    cout << endl;
    graph.FindPath(start, mm, count);
    cout << count;

    // 释放动态内存
    delete[] verArr;
    for (int i = 0; i < m; ++i)
    {
        delete[] edgeArr[i];
    }
    delete[] edgeArr;
    delete[] weightArr;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Juneeeeeeeeeeeee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值