[关闭]
@rg070836rg 2015-12-26T15:27:20.000000Z 字数 2638 阅读 1501

算法概论实验十一

算法概论实验

  1. 实验十一
  2. 实验目的与要求:
  3. 1 掌握对无向图的2-连通分量的划分算法。
  4. 2 理解与掌握在含负权值边的图中求最短路径问题的算法。
  5. 1.无向图的双连通分量问题
  6. 【问题描述】
  7. 给定一个无向图,设计一个算法,判断该图中是否存在关节点,并划分双连通分量。
  8. 2.带负权值边的有向图中的最短路径路径问题
  9. 【问题描述】
  10. 对于一个带负权值边的有向图,实现Bellman-Ford算法,求出从指定顶点s到其余顶点的最短路径,并判断图中是否存在负环。

1.无向图的双连通分量问题

1.1结构化定义

  1. //为了方便输出双联通分量,定义一个结构
  2. struct myedge
  3. {
  4. int start;
  5. int end;
  6. myedge(int a, int b)
  7. {
  8. start = a;
  9. end = b;
  10. }
  11. };
  1. template<class T>
  2. class MGraph
  3. {
  4. public:
  5. MGraph(T v[], int n, int e);//无向图的邻接矩阵建立
  6. MGraph();
  7. virtual ~MGraph();
  8. void Print();//打印图
  9. void print_prepost();//打印prepostback表
  10. int BiDFS(int v);//关节点
  11. private:
  12. int vexnum, edgenum; //vexnum--顶点数 edgenum--边数
  13. vector<vector<int> > edges; //邻接矩阵
  14. vector<vector<bool> > edges_view; //领街边判定表
  15. vector<T> vexs; //顶点表
  16. vector<int> pre;
  17. vector<int> post;
  18. vector<int> back;
  19. vector<int> vex_cnt; //输出辅助计数器
  20. stack<myedge> edgeStack;//边集存储
  21. int clock;
  22. int gettruenum(); //获取判断表中true数量
  23. bool getVexV(int v);//判断是否存在未访问边
  24. myedge getFirstVw(int v);//找到vw边
  25. vector<vector<int>> show_edge;
  26. };

1.2 关键函数

  1. //Bicomponent Algorithm
  2. template<class T>
  3. int MGraph<T>::BiDFS(int v)
  4. {
  5. pre[v] = clock;
  6. clock++;
  7. back[v] = pre[v];
  8. while (getVexV(v))
  9. {
  10. myedge t = getFirstVw(v);
  11. edgeStack.push(t);
  12. vex_cnt[t.start]++;//辅助保存start出现次数
  13. if (pre[t.end] == -1)//如果是tree边
  14. {
  15. int wBack = BiDFS(t.end);
  16. if (wBack >= pre[v])
  17. {
  18. cout << "双连通分量:" << endl;
  19. int tmp = edgeStack.top().end;
  20. if (vex_cnt[tmp] > 0)
  21. {
  22. while (edgeStack.top().start != tmp)
  23. {
  24. cout << vexs[edgeStack.top().start] << "->" << vexs[edgeStack.top().end] << endl;
  25. vex_cnt[edgeStack.top().start]--;
  26. edgeStack.pop();
  27. }
  28. }
  29. cout << vexs[edgeStack.top().start] << "->" << vexs[edgeStack.top().end] << endl;
  30. vex_cnt[edgeStack.top().start]--;
  31. edgeStack.pop();
  32. }
  33. back[v] = min(back[v], wBack);
  34. }
  35. else
  36. {
  37. back[v] = min(pre[t.end], back[v]);
  38. }
  39. }
  40. post[v] = clock;
  41. clock++;
  42. return back[v];
  43. }

1.3 测试函数

  1. int main()
  2. {
  3. //char a[] = { '1', '2', '3', '4', '5','6','7','8' };
  4. char a[] = { 'A', 'B', 'C', 'D', 'E','F','G','H','I','J' };
  5. MGraph<char> m(a, 10, 14);
  6. cout << endl << "打印测试:" << endl;
  7. m.Print();
  8. cout << endl << "关节点测试测试:" << endl;
  9. m.BiDFS(9);
  10. cout << endl;
  11. cout << "pre/post/back值测试:\n";
  12. m.print_prepost();
  13. return 0;
  14. }

1.4 测试截图

1.png-14.7kB

2理解与掌握在含负权值边的图中求最短路径问题的算法

简单,易理解 从源点出发,做V-1次大循环,每次对所有边进行松弛更新

2.1BellmanFord

  1. template <class T>
  2. bool MGraph<T>::BellmanFord(int source)
  3. {
  4. dist[source] = 0;
  5. for (int i = 1; i <= vexnum - 1; i++)
  6. {
  7. for (int u = 0; u < vexnum;u++)
  8. {
  9. for (int v = 0; v<vexnum;v++)
  10. {
  11. if (edges_view[u][v]==true)
  12. {
  13. update(u, v, edges[u][v]);
  14. }
  15. }
  16. }
  17. }
  18. // 判断是否有负环路
  19. for (int u = 0; u < vexnum; u++)
  20. {
  21. for (int v = 0; v < vexnum; v++)
  22. {
  23. if (edges_view[u][v] == true)
  24. {
  25. if (dist[v] > dist[u] + edges[u][v])
  26. {
  27. return false;
  28. }
  29. }
  30. }
  31. }
  32. return true;
  33. }

2.2更新

  1. template <class T>
  2. void MGraph<T>::update(int u, int v, int weight)
  3. {
  4. if (dist[v] > dist[u] + weight)
  5. dist[v] = dist[u] + weight;
  6. }

2.3测试函数

  1. int main()
  2. {
  3. //char a[] = { 's', '2', '3', '4', '5','6','7','t' };
  4. //char a[] = { 'A', 'B', 'C', 'D', 'E','F','G','H','I','J' };
  5. char a[] = { 'A', 'B', 'C', 'D', 'E'};
  6. MGraph<char> m(a, 5, 8);
  7. cout << endl << "打印测试:" << endl;
  8. m.Print();
  9. m.Print_dist(1);
  10. return 0;
  11. }

2.4测试截图

2.png-9.6kB
3.png-14.3kB

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注