• 1、拓扑排序 2、逆拓扑 3、i到j之间长度为k的路径 4、i到j之间包含顶点x的路径是否存在 5、如果边是带权的,求解 i 到 j 之间长度最长的路径


    目录

    1、拓扑排序

    2、逆拓扑

    3、i到j之间长度为k的路径

    4、i到j之间包含顶点x的路径是否存在

    5、如果边是带权的,求解 i 到 j 之间长度最长的路径


    1、拓扑排序

    1. /**
    2. * 内容:
    3. * 1、拓扑排序
    4. * 2、逆拓扑
    5. * 3、i到j之间长度为k的路径
    6. * 4、i到j之间包含顶点x的路径是否存在
    7. * 5、如果边是带权的,求解 i 到 j 之间长度最长的路径
    8. *
    9. * ①算法思想
    10. * 1、每一轮把一个入度为0的顶点加入到一个存储结构里面(栈或队列),然后从栈或队列中取出一个入度为0的元素,在图上做一个逻辑上的删除,
    11. * 删除后减少相关顶点的入度(GetIndegreeX),再次将入度为0的顶点加入到存储结构里,直到逻辑删除完毕所有的顶点。
    12. * 2、有三种方法实现逆拓扑:
    13. * 法1:不断逻辑删除出度为0的顶点。(拓扑排序是不断删除入度为0的顶点)
    14. * 法2:使用DFS,可以想象一下,DFS 一直往深处遍历,直到遍历到这一轮的最后一个节点,说明这
    15. * 个节点没有下一个了,说明没有出度,只有入度,那么理应是拓扑排序中的最后一个,那么也就是逆拓扑排序中的第一个。
    16. * 法3:先拓扑排序,最后一步将输出逆置。
    17. * 3、求i到j之间长度为 length 的路径(拿PathIsSimple()改来的)
    18. * 4、i到j之间包含顶点 x 的路径(拿PathIsSimple()改来的)
    19. * 5、如果边是带权的,求解 i 到 j 之间长度最长的路径(拿PathIsSimple()改来的)
    20. *
    21. * ②算法设计
    22. *
    23. */
    24. #include <stdio.h>
    25. #include <iostream>
    26. #include <cstdio>
    27. #include <malloc.h>
    28. #include <cstdlib>
    29. #define MaxSize 20
    30. #define INF 999999
    31. struct ArcNode{
    32. int adjvex;
    33. struct ArcNode *next;
    34. int weight;
    35. };
    36. struct VNode{
    37. char value;
    38. struct ArcNode *first;
    39. };
    40. struct AdGraph{
    41. VNode vertices[MaxSize];
    42. int vexnum,arcnum;
    43. };
    44. //1、拓扑排序(可以判断有向联通图是否有环,如果不是连通图那么就对几个子部分分别进行判断)
    45. //求顶点入度:
    46. //复习:求某个顶点的入度:
    47. //int GetInDegreeX(AdGraph G,int v){
    48. // int degree = 0;
    49. // ArcNode *p;
    50. // for (int i = 0; i < G.vexnum; ++i) {
    51. // p = G.vertices[i].first;
    52. // while(p){
    53. // if(p -> adjvex == v)
    54. // degree ++;
    55. // p = p -> next;
    56. // }
    57. // }
    58. // return degree;
    59. //}
    60. //求所有顶点入度:
    61. void GetAllNodeInDegree(AdGraph G,int *indegree){
    62. for (int i = 0; i < G.vexnum; ++i) {
    63. ArcNode *p = G.vertices[i].first;
    64. while(p){
    65. indegree[p -> adjvex]++;//入度++
    66. p = p -> next;
    67. }
    68. }
    69. }
    70. //Topo函数
    71. bool Topo(AdGraph G){
    72. int Stack[MaxSize],top = -1;//保存入度为0的顶点
    73. int indegree[MaxSize];
    74. int topoSequece[MaxSize],count = 0,v;//topoSequece[]用来保存拓扑序列,count用来标记存储到哪一块了
    75. for (int i = 0; i < G.vexnum; ++i) {
    76. indegree[i] = 0;
    77. }
    78. GetAllNodeInDegree(G,indegree);
    79. //把入度为0的顶点入栈
    80. for (int i = 0; i < G.vexnum; ++i) {
    81. if(indegree[i] == 0){
    82. Stack[++top] = i;
    83. }
    84. }
    85. while(top != -1){
    86. v = Stack[top--];
    87. topoSequece[count++] = v;//出栈后加入topo序列
    88. ArcNode *p = G.vertices[v].first;
    89. while(p){
    90. //下面两句也可以这样写:
    91. //if(!(--indegree[p -> adjvex]){...}
    92. indegree[p -> adjvex]--;
    93. if(indegree[p -> adjvex] == 0){
    94. Stack[++top] = p -> adjvex;
    95. }
    96. p = p -> next;
    97. }
    98. }
    99. //打印topoSequence
    100. for (int i = 0; i < count; ++i) {
    101. printf("%d ",topoSequece[i]);
    102. }
    103. if(count == G.vexnum)//说明拓扑序列里的元素数量和G的顶点数量相同,也就是所有元素都进入过Stack栈,说明所有元素逻辑上都入度为0
    104. return true;
    105. else
    106. return false;
    107. }


    2、逆拓扑

    1. //2、逆拓扑
    2. //方法①:删除出度为0的节点
    3. //求所有顶点出度:
    4. void GetAllNodeOutDegree(AdGraph G,int *outdegree){
    5. for (int i = 0; i < G.vexnum; ++i) {
    6. ArcNode *p = G.vertices[i].first;
    7. while(p){
    8. outdegree[i]++;//出度++
    9. p = p -> next;
    10. }
    11. }
    12. }
    13. //逆Topo函数
    14. bool ReTopo(AdGraph G){
    15. int Stack[MaxSize],top = -1;//保存入度为0的顶点
    16. int outdegree[MaxSize];
    17. int RetopoSequence[MaxSize],count = 0,v;//RetopoSequece[]用来保存拓扑序列,count用来标记存储到哪一块了
    18. for (int i = 0; i < G.vexnum; ++i) {
    19. outdegree[i] = 0;
    20. }
    21. GetAllNodeOutDegree(G,outdegree);
    22. //把出度为0的顶点入栈
    23. for (int i = 0; i < G.vexnum; ++i) {
    24. if(outdegree[i] == 0){
    25. Stack[++top] = i;
    26. }
    27. }
    28. //从网中将指向v顶点的顶点的度--
    29. while(top != -1){
    30. v = Stack[top--];
    31. RetopoSequence[count++] = v;//出栈后加入topo序列
    32. for (int i = 0; i < G.vexnum; ++i) {
    33. ArcNode *p = G.vertices[i].first;
    34. while(p){
    35. //下面两句也可以这样写:
    36. //if(!(--indegree[p -> adjvex]){...}
    37. if(p -> adjvex == v)
    38. outdegree[i]--;
    39. if(outdegree[i] == 0){
    40. Stack[++top] = i;
    41. }
    42. p = p -> next;
    43. }
    44. }
    45. }
    46. //将RetopoSequence数组里的元素输出
    47. for (int i = 0; i < count; ++i) {
    48. printf("%d ",RetopoSequence[i]);
    49. }
    50. if(count == G.vexnum)//说明拓扑序列里的元素数量和G的顶点数量相同,也就是所有元素都进入过Stack栈,说明所有元素逻辑上都入度为0
    51. return true;
    52. else
    53. return false;
    54. }
    55. //方法②:使用DFS,DFS元素在出栈前进行输出就是逆拓扑(已知是无环的情况下才能使用DFS)
    56. //回顾DFS
    57. void DFS(AdGraph G,int v,int *visited){
    58. visited[v] = 1;
    59. printf("%c ",G.vertices[v].value);
    60. ArcNode *p = G.vertices[v].first;
    61. while(p){//边链表是断断续续访问完的
    62. if(!visited[p -> adjvex]){
    63. DFS(G,p -> adjvex,visited);
    64. }
    65. p = p -> next;
    66. }
    67. }
    68. //用DFS实现逆拓扑(已知是无环的情况下)
    69. void ReverseTopo(AdGraph G,int v,int *visited){
    70. visited[v] = 1;
    71. ArcNode *p = G.vertices[v].first;
    72. while(p){//边链表是断断续续访问完的
    73. if(!visited[p -> adjvex]){
    74. ReverseTopo(G,p -> adjvex,visited);
    75. }
    76. p = p -> next;
    77. }
    78. printf("%d ",v);
    79. }
    80. //方法③:将拓扑排序序列逆置输出
    81. //求所有顶点入度:
    82. void GetAllNodeInDegree(AdGraph G,int *indegree){
    83. for (int i = 0; i < G.vexnum; ++i) {
    84. ArcNode *p = G.vertices[i].first;
    85. while(p){
    86. indegree[p -> adjvex]++;//入度++
    87. p = p -> next;
    88. }
    89. }
    90. }
    91. //逆Topo函数
    92. bool ReTopo(AdGraph G){
    93. int Stack[MaxSize],top = -1;//保存入度为0的顶点
    94. int indegree[MaxSize];
    95. int RetopoSequence[MaxSize],count = 0,v;//RetopoSequece[]用来保存拓扑序列,count用来标记存储到哪一块了
    96. for (int i = 0; i < G.vexnum; ++i) {
    97. indegree[i] = 0;
    98. }
    99. GetAllNodeInDegree(G,indegree);
    100. //把入度为0的顶点入栈
    101. for (int i = 0; i < G.vexnum; ++i) {
    102. if(indegree[i] == 0){
    103. Stack[++top] = i;
    104. }
    105. }
    106. while(top != -1){
    107. v = Stack[top--];
    108. RetopoSequence[count++] = v;//出栈后加入topo序列
    109. ArcNode *p = G.vertices[v].first;
    110. while(p){
    111. //下面两句也可以这样写:
    112. //if(!(--indegree[p -> adjvex]){...}
    113. indegree[p -> adjvex]--;
    114. if(indegree[p -> adjvex] == 0){
    115. Stack[++top] = p -> adjvex;
    116. }
    117. p = p -> next;
    118. }
    119. }
    120. //将RetopoSequence数组里的元素逆置输出
    121. for (int i = count - 1; i >= 0; i--) {
    122. printf("%d ",RetopoSequence[i]);
    123. }
    124. if(count == G.vexnum)//说明拓扑序列里的元素数量和G的顶点数量相同,也就是所有元素都进入过Stack栈,说明所有元素逻辑上都入度为0
    125. return true;
    126. else
    127. return false;
    128. }


    3、i到j之间长度为k的路径

    1. //3、求i到j之间长度为length的路径
    2. //d的初值是0
    3. void PathIJ_length(AdGraph G,int i,int j,int *path,int d,int *visited,int length){//path是个数组,用于保存i到j的路径,d用来表示存入path数组的下标位置
    4. path[d] = i;
    5. if(i == j && d == length){
    6. for (int k = 0; k <= d; ++k) {//有个=是为了把j这个点的值也输出出来
    7. printf("%c ",G.vertices[path[k]].value);
    8. }
    9. }
    10. visited[i] = 1;
    11. ArcNode *p = G.vertices[i].first;
    12. while(p){//回退来之后,会直接走一下步没有被访问到的点,
    13. if(!visited[p -> adjvex]){//如果这个点没有被访问过,(保证了不会访问重复顶点)就调用自身
    14. PathIJ_length(G,p -> adjvex,j,path,d + 1,visited,length);
    15. }
    16. p = p -> next;
    17. }
    18. visited[i] = 0;
    19. //如果不置零,只能求出来一个唯一的长度为length的路径,但要求的是所有长度为length的路径。
    20. //因为某个顶点在这条长度为length的路径中被访问了之后,不一定说不是构成别的长度为length的路径所需要的顶点。
    21. }


    4、i到j之间包含顶点x的路径是否存在

    1. //4、i到j之间包含顶点x的路径是否存在
    2. //d的初值是0,刚开始is0,代表不存在
    3. void PathIJ_X(AdGraph G,int i,int j,int *path,int d,int *visited,int x,int &is){//path是个数组,用于保存i到j的路径,d用来表示存入path数组的下标位置
    4. path[d] = i;
    5. if(i == j){
    6. for (int k = 0; k <= d; ++k) {
    7. if(path[k] == x)
    8. is = 1;
    9. }
    10. }
    11. visited[i] = 1;
    12. ArcNode *p = G.vertices[i].first;
    13. while(p){//回退来之后,会直接走一下步没有被访问到的点,
    14. if(!visited[p -> adjvex]){//如果这个点没有被访问过,(保证了不会访问重复顶点)就调用自身
    15. PathIJ_X(G,p -> adjvex,j,path,d + 1,visited,x,is);
    16. }
    17. p = p -> next;
    18. }
    19. visited[i] = 0;//如果不置零,只能求出来一个唯一的路径,但要求的是所有简单路径。
    20. //因为某个顶点在这条路径中被访问了之后,不一定说不是别的路径所需要的顶点。
    21. }


    5、如果边是带权的,求解 i 到 j 之间长度最长的路径

    1. //5、如果边是带权的,求解 i 到 j 之间长度最长的路径
    2. struct MGraph{
    3. char vex[MaxSize];
    4. int weight[MaxSize][MaxSize];
    5. int vexnum,arcnum;
    6. };
    7. //d的初值是0,刚开始is0,代表不存在
    8. //有了路径之后,要保存路径的长度,新传入一个参数maxlength
    9. void PathIJ_MaxLength(MGraph G,int i,int j,int *path,int d,int *visited,int &maxLength,int *maxPath,int count){
    10. //path是个数组,用于保存i到j的路径,d用来表示存入path数组的下标位置,
    11. //maxPath是个数组,用来拷贝maxLength最大的那个路径,也就是最长路径,count用来保存maxPath数组有多少个值,初值count=0
    12. path[d] = i;//path[]存的是路过的顶点的下标
    13. int sum = 0;//用来保存路径长度,刚开始是0
    14. if(i == j){
    15. //保存此条路径的长度
    16. for (int k = 0; k < d; ++k) {//这边不用再k=d了
    17. sum += G.weight[path[k]][path[k + 1]];//两顶点之间的长度
    18. }
    19. if(maxLength < sum){
    20. maxLength = sum;
    21. for (int k = 0; k <= d; ++k) {
    22. maxPath[count++] = path[k];
    23. }
    24. }
    25. }
    26. visited[i] = 1;
    27. for (int k = 0; k < G.vexnum; ++k) {
    28. if(G.weight[i][k] != 0 && G.weight[i][k] != INF && visited[k] == 0){
    29. //如果两点间有权值(即有边)并且不是INF并且这个点没有被访问过
    30. PathIJ_MaxLength(G,k,j,path,d,visited,maxLength,maxPath,count);
    31. }
    32. }
    33. visited[i] = 0;//如果不置零,只能求出来一个唯一的路径,但要求的是所有路径。
    34. //因为某个顶点在这条最长路径中被访问了之后,不一定说不是构成别的最长路径所需要的顶点。
    35. }

  • 相关阅读:
    我国智慧燃气建设应用过程中,有哪些关键问题?
    Oracle考证对我们有什么帮助?
    章节六:带参数请求数据
    Go 语言编译环境
    组件——组件名、非单文件组件、单文件组件
    java计算机毕业设计工资管理系统源码+mysql数据库+系统+lw文档+部署
    Linux学习记录——사 权限与工具
    MIPI CSI-2笔记(18) -- 数据格式(RAW图像数据)
    微信支付证V3
    护眼灯防蓝光什么意思?2022最新的护眼效果最好的led护眼灯推荐
  • 原文地址:https://blog.csdn.net/shengruyu/article/details/126918488