c++有向图中顶点的路径问题



c++有向图中顶点的路径问题。

主要解决三个问题:

前提:有向图+邻接矩阵存储

问题1、判断有向图中是否存在顶点u到v的路径

问题2、求u到v的所有简单路径

问题3、求u到v长度为k的简单路径

具体如下:

问题1:判断有向图中是否存在顶点u到v的路径

方法:可以使用深度遍历或广度遍历

源代码:

  1. #include <iostream>
  2. using namespace std;
  3. const int MAX_Vertex_Num = 20;
  4. template<class VexType,class ArcType>
  5. class MGraph
  6. {
  7. public:
  8.     void CreateGraph();//创建图
  9.     int LocateVex(VexType v);//返回顶点v所在顶点向量中的位置(下标)
  10.     bool getPathiToj(VexType u1,VexType u2);
  11. private:
  12.     VexType vexs[MAX_Vertex_Num];//顶点向量
  13.     ArcType arcs[MAX_Vertex_Num][MAX_Vertex_Num];
  14.     int vexnum;//顶点数
  15.     int arcnum;//边数
  16. private:
  17.     void getPathiToj_DFS(int x,int y,int num,bool& isFind,bool visited[MAX_Vertex_Num],int path[MAX_Vertex_Num]);//借助DFS的思想实现
  18. };
  19. template<class VexType,class ArcType>
  20. void MGraph<VexType,ArcType>::CreateGraph()
  21. {
  22.     VexType first;
  23.     VexType Secend;
  24.     cout<<”请输入顶点数:”;
  25.     cin>>vexnum;
  26.     cout<<”请输入边数:”;
  27.     cin>>arcnum;
  28.     cout<<”请输入各个顶点值:”;
  29.     for (int i=0;i<vexnum;i++)
  30.     {
  31.         cin>>vexs[i];
  32.     }
  33.     //初始化邻接矩阵
  34.     for (int i=0;i<arcnum;i++)
  35.     {
  36.         for (int j=0;j<arcnum;j++)
  37.         {
  38.             arcs[i][j]=0;
  39.         }
  40.     }
  41.     cout<<”请输入边的信息:”<<endl;
  42.     for (int i=0;i<arcnum;i++)
  43.     {
  44.         cin>>first>>Secend;
  45.         //如果边有权值的话,则还应该输入权值
  46.         int x = LocateVex(first);
  47.         int y = LocateVex(Secend);
  48.         arcs[x][y]=1;//如果是有权的话,这里应该是arc[x][y]=权值
  49.         //arcs[y][x]=1;//无向图是对称的
  50.     }
  51. }
  52. /*
  53. 参数:v:表示顶点向量中一个值
  54. 函数返回值:函数返回v在顶点向量中的下标
  55. */
  56. template<class VexType,class ArcType>
  57. int MGraph<VexType,ArcType>::LocateVex(VexType v)
  58. {
  59.     for (int i=0;i<vexnum;i++)
  60.     {
  61.         if (vexs[i]==v)
  62.         {
  63.             return i;
  64.         }
  65.     }
  66.     return -1;
  67. }
  68. /*
  69. 返回顶点u1到u2之间的路径
  70. 参数:
  71. u1:表示起始顶点
  72. u2:表示终点顶点
  73. */
  74. template<class VexType,class ArcType>
  75. bool MGraph<VexType,ArcType>::getPathiToj(VexType u1,VexType u2)
  76. {
  77.     bool isFind=false;
  78.     int num=0;//两个顶点存在路径时,之间的顶点数
  79.     int x = LocateVex(u1);
  80.     int y = LocateVex(u2);
  81.     bool visited[MAX_Vertex_Num]={false};
  82.     int path[MAX_Vertex_Num];
  83.     visited[x]=true;
  84.     path[0]=x;
  85.     getPathiToj_DFS(x,y,num+1,isFind,visited,path);
  86.     return isFind;
  87. }
  88. /*
  89. 返回 x指向的起始顶点 到 y指向的终点顶点 的所有路径
  90. 参数:
  91. x表示起始顶点的坐标,一直在变化
  92. y表示终点顶点的坐标,一直保持不变
  93. num:现在路径中的顶点个数
  94. visited数组:表示每个顶点是不是已经访问过
  95. path数组:用来存放每条路径
  96. */
  97. template<class VexType,class ArcType>
  98. void MGraph<VexType,ArcType>::getPathiToj_DFS(int x,int y,int num,bool& isFind,bool visited[MAX_Vertex_Num],int path[MAX_Vertex_Num])
  99. {
  100.     for (int j=0;j<vexnum;j++)
  101.     {
  102.         if (arcs[x][j]==1 && visited[j]==false)
  103.         {
  104.             path[num]=j;//每遇到一个顶点都要该顶点都放到数组中
  105.             visited[j]=true;
  106.             if (j==y)//到达目的节点,输出路径
  107.             {
  108.                 isFind = true;
  109.                 cout<<”顶点”<<vexs[0]<<”到”<<vexs[j]<<”的路径为:”;
  110.                 for (int i=0;i<num+1;i++)
  111.                 {
  112.                     cout<<vexs[path[i]];
  113.                 }
  114.                 cout<<endl;
  115.                 //找到终点,此时本次查找结束
  116.             }
  117.             else//当没有找到时,要继续往下一层寻找
  118.             {
  119.                 getPathiToj_DFS(j,y,num+1,isFind,visited,path);//无论此时找没找到终点,总是要往下走的
  120.             }
  121.             visited[j]=false;//回溯,恢复现场。当走下一次循环时,要把上一次递归过程中访问到的结点都恢复到起始状态,重新处理
  122.         }
  123.     }
  124. }
  125. int main()
  126. {
  127.     MGraph<char,int> G;
  128.     G.CreateGraph();
  129.     if (!G.getPathiToj(‘A’,'J’))
  130.     {
  131.         cout<<”A到J之间不存在路径!”<<endl;
  132.     }
  133.     if (!G.getPathiToj(‘A’,'G’))
  134.     {
  135.         cout<<”A到G之间不存在路径!”<<endl;
  136.     }
  137.     system(“pause”);
  138.     return 1;
  139. }

结果测试:


有向图:

输出结果:

问题3、

方法:使用回溯法

源代码:

  1. #include <iostream>
  2. using namespace std;
  3. const int MAX_Vertex_Num = 20;
  4. template<class VexType,class ArcType>
  5. class MGraph
  6. {
  7. public:
  8.     void CreateGraph();//创建图
  9.     int LocateVex(VexType v);//返回顶点v所在顶点向量中的位置(下标)
  10.     bool getPathiToj(VexType u1,VexType u2,int k);
  11. private:
  12.     VexType vexs[MAX_Vertex_Num];//顶点向量
  13.     ArcType arcs[MAX_Vertex_Num][MAX_Vertex_Num];
  14.     int vexnum;//顶点数
  15.     int arcnum;//边数
  16. private:
  17.     void getPathiToj_DFS(int x,int y,int num,int k,bool& isFind,bool visited[MAX_Vertex_Num],int path[MAX_Vertex_Num]);//借助DFS的思想实现
  18. };
  19. template<class VexType,class ArcType>
  20. void MGraph<VexType,ArcType>::CreateGraph()
  21. {
  22.     VexType first;
  23.     VexType Secend;
  24.     cout<<”请输入顶点数:”;
  25.     cin>>vexnum;
  26.     cout<<”请输入边数:”;
  27.     cin>>arcnum;
  28.     cout<<”请输入各个顶点值:”;
  29.     for (int i=0;i<vexnum;i++)
  30.     {
  31.         cin>>vexs[i];
  32.     }
  33.     //初始化邻接矩阵
  34.     for (int i=0;i<arcnum;i++)
  35.     {
  36.         for (int j=0;j<arcnum;j++)
  37.         {
  38.             arcs[i][j]=0;
  39.         }
  40.     }
  41.     cout<<”请输入边的信息:”<<endl;
  42.     for (int i=0;i<arcnum;i++)
  43.     {
  44.         cin>>first>>Secend;
  45.         //如果边有权值的话,则还应该输入权值
  46.         int x = LocateVex(first);
  47.         int y = LocateVex(Secend);
  48.         arcs[x][y]=1;//如果是有权的话,这里应该是arc[x][y]=权值
  49.         //arcs[y][x]=1;//无向图是对称的
  50.     }
  51. }
  52. /*
  53. 参数:v:表示顶点向量中一个值
  54. 函数返回值:函数返回v在顶点向量中的下标
  55. */
  56. template<class VexType,class ArcType>
  57. int MGraph<VexType,ArcType>::LocateVex(VexType v)
  58. {
  59.     for (int i=0;i<vexnum;i++)
  60.     {
  61.         if (vexs[i]==v)
  62.         {
  63.             return i;
  64.         }
  65.     }
  66.     return -1;
  67. }
  68. /*
  69. 返回顶点u1到u2之间的路径
  70. 参数:
  71. u1:表示起始顶点
  72. u2:表示终点顶点
  73. */
  74. template<class VexType,class ArcType>
  75. bool MGraph<VexType,ArcType>::getPathiToj(VexType u1,VexType u2,int k)
  76. {
  77.     bool isFind=false;
  78.     int num=0;//两个顶点存在路径时,之间的顶点数
  79.     int x = LocateVex(u1);
  80.     int y = LocateVex(u2);
  81.     bool visited[MAX_Vertex_Num]={false};
  82.     int path[MAX_Vertex_Num];
  83.     visited[x]=true;
  84.     path[0]=x;
  85.     getPathiToj_DFS(x,y,num+1,k,isFind,visited,path);
  86.     return isFind;
  87. }
  88. /*
  89. 返回 x指向的起始顶点 到 y指向的终点顶点 的所有路径
  90. 参数:
  91. x表示起始顶点的坐标,一直在变化
  92. y表示终点顶点的坐标,一直保持不变
  93. num:现在路径中的顶点个数
  94. visited数组:表示每个顶点是不是已经访问过
  95. path数组:用来存放每条路径
  96. */
  97. template<class VexType,class ArcType>
  98. void MGraph<VexType,ArcType>::getPathiToj_DFS(int x,int y,int num,int k,bool& isFind,bool visited[MAX_Vertex_Num],int path[MAX_Vertex_Num])
  99. {
  100.     for (int j=0;j<vexnum;j++)
  101.     {
  102.         if (arcs[x][j]==1 && visited[j]==false)
  103.         {
  104.             path[num]=j;//每遇到一个顶点都要该顶点都放到数组中
  105.             visited[j]=true;
  106.             if (j==y && num==k)//到达目的节点,输出路径(num表示结点个数,k表示边的个数,但是要注意num=1时,表示有两个顶点)
  107.             {
  108.                 isFind = true;
  109.                 cout<<”顶点A到J之间长度为”<<k<<”的路径为: ”;
  110.                 for (int i=0;i<num+1;i++)
  111.                 {
  112.                     cout<<vexs[path[i]];
  113.                 }
  114.                 cout<<endl;
  115.                 //找到终点,此时本次查找结束
  116.             }
  117.             else//当没有找到时,要继续往下一层寻找
  118.             {
  119.                 getPathiToj_DFS(j,y,num+1,k,isFind,visited,path);//无论此时找没找到终点,总是要往下走的
  120.             }
  121.             visited[j]=false;//回溯,恢复现场。当走下一次循环时,要把上一次递归过程中访问到的结点都恢复到起始状态,重新处理
  122.         }
  123.     }
  124. }
  125. int main()
  126. {
  127.     MGraph<char,int> G;
  128.     G.CreateGraph();
  129.     for (int k=1;k<5;k++)
  130.     {
  131.         if (!G.getPathiToj(‘A’,'J’,k))
  132.         {
  133.             cout<<”顶点A到J之间不存在长度为”<<k<<”的路径!”<<endl;
  134.         }
  135.     }
  136.     system(“pause”);
  137.     return 1;
  138. }

结果测试:

有向图:

结果: