• ACM模板二:树、图、并查集、DancingLink


    目录

    〇,全文说明、宏定义代码

    一,二叉树

    1,代码

    2,测试代码

    二,树状数组、线段树

    1,代码

    2,测试代码

    三,多叉树、RMQ、LCA

    1,代码

    2,测试代码

    四,DancingLink、Covering

    1,代码

    2,测试代码

    五,并查集、无向图、最小生成树Kruskal

    1,代码

    2,测试代码

    六,最小生成树Prim

    1,代码

    2,测试代码

    七,有向图、单源最短路径、连通分量、拓扑排序

    1,代码

    2,测试代码

    八,网格图、回路链路、路径重建

    1,代码

    2,测试代码


    〇,全文说明、宏定义代码

    类里面和宏定义处都有接口注释,因为宏不体现具体参数,所以注释以类里面的为准。

    代码工程结构:

    • 每一章的第一节《代码》可以独立编译运行(本地要加LOCAL宏)
    • 每一章的第二节《测试代码》搭配第〇章的代码和本章第一节的代码可以编译运行并测试成功
    • 所有模板文章的第〇章的代码和其他章第一节的《代码》全部汇总起来可以编译运行

    宏定义代码:

    1. #define LOCAL //力扣不要本行代码,其他OJ随意
    2. ///(1)二叉树///
    3. #define MaxDepth BinaryTree::maxDepth//求二叉树的深度,根节点深度是1
    4. #define MinDepth BinaryTree::minDepth//叶子节点的最小深度
    5. #define PreorderTraversal BinaryTree::preorderTraversal//二叉树的前序遍历
    6. #define PostorderTraversal BinaryTree::postorderTraversal//二叉树的后序遍历
    7. #define InorderTraversal BinaryTree::inorderTraversal//二叉树的中序遍历
    8. #define LevelOrderTraversal BinaryTree::levelOrderTraversal//二叉树的层序遍历
    9. #define BuildTreePre BinaryTree::buildTreePre//根据前序和中序重建二叉树,假设没有重复数字
    10. #define BuildTreePost BinaryTree::buildTreePost//根据中序和后序重建二叉树,假设没有重复数字
    11. #define CountNodes BinaryTree::countNodes//求节点个数
    12. #define CopyTree BinaryTree::copyTree//拷贝二叉树
    13. #define IsSameTree BinaryTree::isSameTree//判断两棵二叉树是否全等
    14. #define InvertTree BinaryTree::invertTree//左右翻转二叉树
    15. ///(2)树状数组、线段树///
    16. // TreeArray 树状数组
    17. // TreeArray2D 二维树状数组
    18. // SegmentTree 线段树
    19. ///(3)多叉树、RMQ、LCA///
    20. #define EdgesToMultiTree MultiTree::edgesToMultiTree//输入无向图,构造多叉生成树
    21. // TreeWithId 略。//把二叉树或多叉树转成id形式的树,前序遍历,从0开始编号
    22. // RMQ 略。
    23. // LCA 略。
    24. ///(4)DancingLink、Covering///
    25. // DancingLink 略。精确覆盖算法
    26. #define GetEdgeCover Covering::getEdgeCover//给定一个2n个点的图,选出n条边,刚好覆盖这2n个点
    27. ///(5.1)并查集///
    28. // Union 略。并查集
    29. // UnionDif 略。
    30. // Vunion 略。
    31. ///(5.2)无向图///
    32. #define EdgesToBinaryTree UndirectedGraph::edgesToBinaryTree//输入二叉树的边集,生成任意一棵二叉树
    33. #define UndirectedEdgeToFatherList UndirectedGraph::undirectedEdgeToFatherList//无向拓扑排序,输入无向无环图{{1,2}{1,3}{4,3}}的邻接表和指定根1,输出父节点表{4:3, 3:1, 2:1}
    34. #define HasUndirectedCircle UndirectedGraph::hasUndirectedCircle//根据无向图的邻接表判断是否有环
    35. #define IsCompleteGraph UndirectedGraph::isCompleteGraph//判断是不是k-正则图
    36. #define IsTwoDivGraph UndirectedGraph::isTwoDivGraph//判断是不是二分图
    37. ///(5.3)最小生成树Kruskal///
    38. #define KruskalMinCostTree Kruskal::kruskalMinCostTree
    39. ///(6)最小生成树Prim///
    40. #define PrimminCostTree Prim::minCostConnectPoints
    41. ///(7.1)有向图///
    42. #define ReverseGraph DirectedGraph::reverseGraph//构建有向图的反向图
    43. #define GetLongestPath DirectedGraph::getLongestPath//求有向无环图中的最长路径长度,出参nextNode是每个点的后继,len是每个点出发的最长路径长度
    44. #define HasDirectedCircle DirectedGraph::hasCircle//根据有向图的邻接表判断是否有环
    45. ///(7.2)单源最短路径///
    46. #define DijskraShortestPath Dijskra::shortestPath//求最短路,适用于不存在负权值的边的图
    47. #define BellmanFordShortestPath BellmanFord::shortestPath//求最短路,适用于不存在负权值的环的图
    48. #define SPFAShortestPath SPFA::shortestPath//求最短路,适用于不存在负权值的环的图
    49. ///(7.3)不区分有向图和无向图的通用操作///
    50. #define GetSubGraph GraphOpt::getSubGraph//根据点集取子图
    51. ///(7.4)连通分量、拓扑排序///
    52. #define SemiConnectComponent SemiConnect::semiConnectComponent//半连通分量分割
    53. #define ConnectComponent KosarajuStrongConnect::connectComponent//Kosaraju算法,强连通分量分割
    54. #define GetPointGraph KosarajuStrongConnect::getPointGraph//强连通分量缩点
    55. // TarjanUndirect 略。Tarjan算法,双连通分量分割
    56. // TarjanStrongConnect 略。Tarjan算法,强连通分量分割
    57. #define TopoSortNoCircle DirectedTopoSort::topoSortNoCircle //有向无环图拓扑排序,输入n=3,g.edges={{0,1}{0,2}{1,2}}, 输出{0,1,2},有环则输出为空
    58. #define TopoSort DirectedTopoSort::topoSort //有向图拓扑排序
    59. ///(8.1)网格图///
    60. // GridGraph 略
    61. ///(8.2)回路或链路///
    62. // Hierholzer 略。欧拉回路或链路
    63. // Hamilton 略。哈密顿回路或链路
    64. ///(8.3)路径重建///
    65. // ReBuild 略。路径重建

    一,二叉树

    1,代码

    1. #ifdef LOCAL
    2. #ifndef struct_TreeNode
    3. #define struct_TreeNode
    4. struct TreeNode {
    5. int val;
    6. TreeNode* left;
    7. TreeNode* right;
    8. TreeNode() : val(0), left(nullptr), right(nullptr) {}
    9. TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    10. TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
    11. };
    12. #endif
    13. #endif
    14. class BinaryTree
    15. {
    16. public:
    17. //求二叉树的深度,根节点深度是1
    18. static int maxDepth(TreeNode* root) {
    19. if (!root)return 0;
    20. return max(maxDepth(root->left), maxDepth(root->right)) + 1;
    21. }
    22. //叶子节点的最小深度
    23. static int minDepth(TreeNode* root) {
    24. if (!root)return 0;
    25. return min_depth(root);
    26. }
    27. //二叉树的前序遍历
    28. static vector<int> preorderTraversal(TreeNode* root) {
    29. vector<int>v1;
    30. if (root == NULL)return v1;
    31. v1.insert(v1.end(), root->val);
    32. vector<int>v2 = preorderTraversal(root->left);
    33. v1.insert(v1.end(), v2.begin(), v2.end());
    34. v2 = preorderTraversal(root->right);
    35. v1.insert(v1.end(), v2.begin(), v2.end());
    36. return v1;
    37. }
    38. //二叉树的后序遍历
    39. static vector<int> postorderTraversal(TreeNode* root) {
    40. vector<int>v1;
    41. if (root == NULL)return v1;
    42. vector<int>v2 = postorderTraversal(root->left);
    43. v1.insert(v1.end(), v2.begin(), v2.end());
    44. v2 = postorderTraversal(root->right);
    45. v1.insert(v1.end(), v2.begin(), v2.end());
    46. v1.insert(v1.end(), root->val);
    47. return v1;
    48. }
    49. //二叉树的中序遍历
    50. static vector<int> inorderTraversal(TreeNode* root) {
    51. vector<int>v1;
    52. if (root == NULL)return v1;
    53. v1 = inorderTraversal(root->left);
    54. v1.insert(v1.end(), root->val);
    55. vector<int>v2 = inorderTraversal(root->right);
    56. v1.insert(v1.end(), v2.begin(), v2.end());
    57. return v1;
    58. }
    59. //二叉树的层序遍历
    60. static vectorint>> levelOrderTraversal(TreeNode* root) {
    61. vectorint>>ans;
    62. if (!root)return ans;
    63. vector>v;
    64. vectortmp;
    65. vector<int>tmpans;
    66. tmp.push_back(root);
    67. v.push_back(tmp);
    68. bfs(v);
    69. for (int i = 0; i < v.size(); i++) {
    70. tmpans.resize(v[i].size());
    71. for (int j = 0; j < v[i].size(); j++)tmpans[j] = v[i][j]->val;
    72. ans.push_back(tmpans);
    73. }
    74. return ans;
    75. }
    76. //根据前序和中序重建二叉树,假设没有重复数字
    77. static TreeNode* buildTreePre(vector<int>& preorder, vector<int>& inorder) {
    78. return build_tree(preorder, 0, inorder, 0, inorder.size());
    79. }
    80. //根据中序和后序重建二叉树,假设没有重复数字
    81. static TreeNode* buildTreePost(vector<int>& inorder, vector<int>& postorder) {
    82. return build_tree2(postorder, 0, inorder, 0, inorder.size());
    83. }
    84. //求节点个数
    85. static int countNodes(TreeNode* root) {
    86. if (!root)return 0;
    87. return countNodes(root->left) + countNodes(root->right) + 1;
    88. }
    89. //拷贝二叉树
    90. static TreeNode* copyTree(TreeNode* root)
    91. {
    92. if (!root)return root;
    93. return new TreeNode(root->val, copyTree(root->left), copyTree(root->right));
    94. }
    95. //判断两棵二叉树是否全等
    96. static bool isSameTree(TreeNode* r1, TreeNode* r2)
    97. {
    98. if (r1 == NULL && r2 == NULL)return true;
    99. if (r1 == NULL || r2 == NULL)return false;
    100. if (r1->val != r2->val)return false;
    101. return isSameTree(r1->left, r2->left) && isSameTree(r1->right, r2->right);
    102. }
    103. //左右翻转二叉树
    104. static TreeNode* invertTree(TreeNode* root) {
    105. if (!root)return root;
    106. TreeNode* p = root->left, *q = root->right;
    107. root->left = q, root->right = p;
    108. invertTree(p);
    109. invertTree(q);
    110. return root;
    111. }
    112. private:
    113. static int min_depth(TreeNode* root) {
    114. if (!root)return 1234567890;
    115. if (!root->left && !root->right)return 1;
    116. return min(min_depth(root->left), min_depth(root->right)) + 1;
    117. }
    118. static void bfs(vector>&v) {
    119. vectorv1 = *(v.end() - 1);
    120. vectorv2;
    121. for (int i = 0; i < v1.size(); i++) {
    122. if (v1[i]->left)v2.push_back(v1[i]->left);
    123. if (v1[i]->right)v2.push_back(v1[i]->right);
    124. }
    125. if (v2.empty())return;
    126. v.push_back(v2);
    127. bfs(v);
    128. }
    129. static TreeNode* build_tree(vector<int>& preorder, int s1, vector<int>& inorder, int s2, int len) {
    130. if (len <= 0)return NULL;
    131. TreeNode* ans = new TreeNode;
    132. ans->val = preorder[s1];
    133. auto loc = find(inorder.begin() + s2, inorder.begin() + s2 + len, preorder[s1]);
    134. ans->left = build_tree(preorder, s1 + 1, inorder, s2, loc - inorder.begin() - s2);
    135. ans->right = build_tree(preorder, loc - inorder.begin() - s2 + s1 + 1, inorder, loc - inorder.begin() + 1, len - (loc - inorder.begin() - s2) - 1);
    136. return ans;
    137. }
    138. static TreeNode* build_tree2(vector<int>& postorder, int s1, vector<int>& inorder, int s2, int len) {
    139. if (len <= 0)return NULL;
    140. TreeNode* ans = new TreeNode;
    141. ans->val = postorder[s1 + len - 1];
    142. auto loc = find(inorder.begin() + s2, inorder.begin() + s2 + len, postorder[s1 + len - 1]);
    143. ans->left = build_tree2(postorder, s1, inorder, s2, loc - inorder.begin() - s2);
    144. ans->right = build_tree2(postorder, loc - inorder.begin() - s2 + s1, inorder, loc - inorder.begin() + 1, len - (loc - inorder.begin() - s2) - 1);
    145. return ans;
    146. }
    147. };

    2,测试代码

    1. template<typename T>
    2. static bool vecIsSame(const vector& v1, const vector& v2)
    3. {
    4. if (v1.size() - v2.size())return false;
    5. for (int i = 0; i < v1.size(); i++)if (v1[i] != v2[i])return false;
    6. return true;
    7. }
    8. #define EXPECT_VEC_EQ(a,b) if(!vecIsSame((a),(b))){cout<<"ERROR!!!!!!!!!\n";return false;}
    9. #define EXPECT_EQ(a,b) if(a!=b){cout<<"ERROR!!!!!!!!!\n";return false;}
    10. bool testBinaryTree()
    11. {
    12. TreeNode t1(1), t2(2), t3(3), t4(4);
    13. t1.left = &t2, t1.right = &t3, t2.left = &t4;
    14. auto p = &t1;
    15. EXPECT_EQ(MaxDepth(p), 3);
    16. EXPECT_EQ(MinDepth(p), 2);
    17. vector<int>pre{ 1, 2, 4, 3 }, post{ 4, 2, 3, 1 }, inorder{ 4, 2, 1, 3 };
    18. EXPECT_VEC_EQ(PreorderTraversal(p), pre);
    19. EXPECT_VEC_EQ(PostorderTraversal(p), post);
    20. EXPECT_VEC_EQ(InorderTraversal(p), inorder);
    21. auto p2 = BuildTreePre(pre, inorder);
    22. EXPECT_EQ(IsSameTree(p, p2), true);
    23. p2 = BuildTreePost(inorder, post);
    24. EXPECT_EQ(IsSameTree(p, p2), true);
    25. EXPECT_EQ(CountNodes(p), 4);
    26. p2 = CopyTree(p);
    27. EXPECT_EQ(IsSameTree(p, p2), true);
    28. InvertTree(p2);
    29. EXPECT_EQ(IsSameTree(p, p2), false);
    30. InvertTree(p2);
    31. EXPECT_EQ(IsSameTree(p, p2), true);
    32. return true;
    33. }
    34. int main()
    35. {
    36. if (testBinaryTree())cout << "test succ!";
    37. return 0;
    38. }

    二,树状数组、线段树

    1,代码

    1. template<int maxLen = 100000>
    2. class TreeArray
    3. {
    4. public:
    5. TreeArray(int len)//len是元素实际数量,元素id范围是[1,n]
    6. {
    7. this->n = len;
    8. memset(c, 0, sizeof(int)*(len + 1));
    9. }
    10. void add(int i, int x)
    11. {
    12. while (i <= n)
    13. {
    14. c[i] += x;
    15. i += (i&(-i));
    16. }
    17. }
    18. int getSum(int i)
    19. {
    20. int s = 0;
    21. while (i)
    22. {
    23. s += c[i];
    24. i -= (i&(-i));
    25. }
    26. return s;
    27. }
    28. private:
    29. int n;
    30. int c[maxLen+5];
    31. };
    32. template<int maxLen = 1000>
    33. class TreeArray2D
    34. {
    35. public:
    36. TreeArray2D(int len)//len是元素实际数量,元素id范围是[1,n]*[1,n]
    37. {
    38. this->n = len;
    39. for (int i = 0; i <= n; i++)memset(c[i], 0, sizeof(int)*(n + 1));
    40. }
    41. void add(int x, int y, int a = 1)
    42. {
    43. for (int i = x; i <= n; i += (i&(-i)))
    44. for (int j = y; j <= n; j += (j&(-j)))c[i][j] += a;
    45. }
    46. int getSum(int x, int y)
    47. {
    48. int s = 0;
    49. for (int i = x; i > 0; i -= (i&(-i)))
    50. for (int j = y; j > 0; j -= (j&(-j)))
    51. s += c[i][j];
    52. return s;
    53. }
    54. private:
    55. int n;
    56. int c[maxLen +5][maxLen +5];
    57. };
    58. //type=0,1,2,3,4分别表示sum型、min型、max型、minId型、maxId型线段树
    59. //maxLen是元素最大数量
    60. template<int type, int maxLen = 100000, typename T = int>
    61. class SegmentTreeBase
    62. {
    63. public:
    64. T* getData()//先调getData更新数据再调build
    65. {
    66. return num;
    67. }
    68. void build(int len)//len是元素实际数量,元素id范围是[1,n]
    69. {
    70. this->n = len;
    71. build(1, 1, n);
    72. }
    73. void update(int uplace, T value)//1<=uplace<=n
    74. {
    75. num[uplace] = value;
    76. update(1, 1, n, uplace);
    77. }
    78. T query(int x, int y)//1<=x<=y<=n
    79. {
    80. return query(1, 1, n, x, y);
    81. }
    82. protected:
    83. template<typename T2>
    84. inline T2 op(T2 a, T2 b)
    85. {
    86. if (type == 3)return num[a] < num[b] ? a : b;
    87. if (type == 4)return num[a] > num[b] ? a : b;
    88. if (type == 0)return a + b;
    89. return type == 1 ? min(a, b) : max(a, b);
    90. }
    91. void build(int key, int low, int high)
    92. {
    93. if (low == high)
    94. {
    95. ans[key] = type > 2 ? low : num[low];
    96. return;
    97. }
    98. int mid = (low + high) / 2;
    99. build(key * 2, low, mid);
    100. build(key * 2 + 1, mid + 1, high);
    101. ans[key] = op(ans[key * 2], ans[key * 2 + 1]);
    102. }
    103. void update(int key, int low, int high, int uplace)
    104. {
    105. if (low == high)
    106. {
    107. ans[key] = type > 2 ? low : num[low];
    108. return;
    109. }
    110. int mid = (low + high) / 2;
    111. if (uplace <= mid)update(key * 2, low, mid, uplace);
    112. else update(key * 2 + 1, mid + 1, high, uplace);
    113. ans[key] = op(ans[key * 2], ans[key * 2 + 1]);
    114. }
    115. T query(int key, int low, int high, int x, int y)
    116. {
    117. if (low == x && high == y)return ans[key];
    118. int mid = (low + high) / 2;
    119. if (mid < x)return query(key * 2 + 1, mid + 1, high, x, y);
    120. if (mid >= y)return query(key * 2, low, mid, x, y);
    121. T a = query(key * 2, low, mid, x, mid);
    122. T b = query(key * 2 + 1, mid + 1, high, mid + 1, y);
    123. return op(a, b);
    124. }
    125. protected:
    126. int n;
    127. T num[maxLen + 1];
    128. T ans[maxLen * 4 + 10];
    129. };
    130. //sum型线段树拓展,支持查询前缀和
    131. template<int maxLen = 100000, typename T = int>
    132. class SegmentTreeTypeSum :public SegmentTreeBase<0, maxLen, T>
    133. {
    134. using BASE = SegmentTreeBase<0, maxLen, T>;
    135. public:
    136. int queryPreSum(T x)
    137. {
    138. return queryPreSum(1, 1, BASE::n, x);
    139. }
    140. private:
    141. int queryPreSum(int key, int low, int high, T x)
    142. {
    143. if (low == high)return low;
    144. int mid = (low + high) / 2;
    145. if (x <= BASE::ans[key * 2])return queryPreSum(key * 2, low, mid, x);
    146. return queryPreSum(key * 2 + 1, mid + 1, high, x - BASE::ans[key * 2]);
    147. }
    148. };
    149. //5种线段树拓展,支持区间更新,区间查询
    150. template<int type, int maxLen = 100000, typename T = int, T invalid = -1>
    151. class SegmentTree :public SegmentTreeBase
    152. {
    153. using BASE = SegmentTreeBase;
    154. public:
    155. void build(int len)//len是元素实际数量,元素id范围是[1,n]
    156. {
    157. BASE::n = len;
    158. build(1, 1, BASE::n);
    159. }
    160. void update(int uplace, T value)//1<=uplace<=n,覆盖父类函数
    161. {
    162. update(uplace, uplace, value);
    163. }
    164. void update(int x, int y, T value)//1<=x<=y<=n
    165. {
    166. update(1, 1, BASE::n, x, y, value);
    167. }
    168. T query(int x, int y)//1<=x<=y<=n
    169. {
    170. return query(1, 1, BASE::n, x, y);
    171. }
    172. private:
    173. static inline T opMulti(T a, int num)
    174. {
    175. if (!type)return a * num;
    176. return a;
    177. }
    178. void build(int key, int low, int high)
    179. {
    180. if (low == high)
    181. {
    182. BASE::ans[key] = type > 2 ? low : BASE::num[low];
    183. lazy[key] = invalid;
    184. return;
    185. }
    186. int mid = (low + high) / 2;
    187. build(key * 2, low, mid);
    188. build(key * 2 + 1, mid + 1, high);
    189. BASE::ans[key] = BASE::op(BASE::ans[key * 2], BASE::ans[key * 2 + 1]);
    190. lazy[key] = invalid;
    191. }
    192. void update(int key, int low, int high, int x, int y, T value)
    193. {
    194. if (low == x && high == y)
    195. {
    196. BASE::ans[key] = type > 2 ? x : opMulti(value, high - low + 1);
    197. lazy[key] = value;
    198. if (x == y)BASE::num[x] = value;
    199. return;
    200. }
    201. if (lazy[key] != invalid)down(key, low, high);
    202. int mid = (low + high) / 2;
    203. if (mid < x)update(key * 2 + 1, mid + 1, high, x, y, value);
    204. else if (mid >= y)update(key * 2, low, mid, x, y, value);
    205. else
    206. {
    207. update(key * 2, low, mid, x, mid, value);
    208. update(key * 2 + 1, mid + 1, high, mid + 1, y, value);
    209. }
    210. BASE::ans[key] = BASE::op(BASE::ans[key * 2], BASE::ans[key * 2 + 1]);
    211. }
    212. void down(int key, int low, int high)
    213. {
    214. int mid = (low + high) / 2;
    215. BASE::ans[key * 2] = type > 2 ? low : opMulti(lazy[key], mid - low + 1);
    216. BASE::ans[key * 2 + 1] = type > 2 ? high : opMulti(lazy[key], high - mid);
    217. lazy[key * 2] = lazy[key];
    218. lazy[key * 2 + 1] = lazy[key];
    219. lazy[key] = invalid;
    220. }
    221. T query(int key, int low, int high, int x, int y)
    222. {
    223. if (low == x && high == y)return BASE::ans[key];
    224. if (lazy[key] != invalid) {
    225. return type > 2 ? x : opMulti(lazy[key], y - x + 1);
    226. }
    227. int mid = (low + high) / 2;
    228. if (mid < x)return query(key * 2 + 1, mid + 1, high, x, y);
    229. if (mid >= y)return query(key * 2, low, mid, x, y);
    230. T a = query(key * 2, low, mid, x, mid);
    231. T b = query(key * 2 + 1, mid + 1, high, mid + 1, y);
    232. return BASE::op(a, b);
    233. }
    234. private:
    235. T lazy[maxLen * 4 + 10];
    236. };

    2,测试代码

    1. #define EXPECT_EQ(a,b) if(a!=b){cout<<"ERROR!!!!!!!!!\n";return false;}
    2. bool testTreeArray()
    3. {
    4. TreeArray<> t(100);
    5. t.add(1, 5);
    6. t.add(3, 10);
    7. EXPECT_EQ(t.getSum(1), 5);
    8. EXPECT_EQ(t.getSum(100), 15);
    9. return true;
    10. }
    11. bool testSegmentTree()
    12. {
    13. SegmentTreeTypeSum<10000> st;
    14. int* num = st.getData();
    15. num[1] = 3, num[2] = 4, num[3] = 2, num[4] = 6;
    16. st.build(4);
    17. st.update(1, 5); //5 4 2 6
    18. EXPECT_EQ(st.query(1, 3), 11);
    19. EXPECT_EQ(st.queryPreSum(5), 1);
    20. EXPECT_EQ(st.queryPreSum(9), 2);
    21. EXPECT_EQ(st.queryPreSum(11), 3);
    22. SegmentTree<1, 10000> stMin;
    23. num = stMin.getData();
    24. num[1] = 3, num[2] = 4, num[3] = 2, num[4] = 6;
    25. stMin.build(4);
    26. stMin.update(2, 3, 5);//3 5 5 6
    27. EXPECT_EQ(stMin.query(1, 4), 3);
    28. EXPECT_EQ(stMin.query(3, 4), 5);
    29. return true;
    30. }
    31. bool test2()
    32. {
    33. return testTreeArray() && testSegmentTree();
    34. }
    35. int main()
    36. {
    37. if (test2())cout << "test succ!";
    38. return 0;
    39. }

    三,多叉树、RMQ、LCA

    1,代码

    1. #ifdef LOCAL
    2. #ifndef struct_TreeNode
    3. #define struct_TreeNode
    4. struct TreeNode {
    5. int val;
    6. TreeNode* left;
    7. TreeNode* right;
    8. TreeNode() : val(0), left(nullptr), right(nullptr) {}
    9. TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    10. TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
    11. };
    12. #endif
    13. #endif
    14. struct MultiTreeNode {
    15. int val = 0;
    16. vectorson{}; //son只存实际有的孩子,son可能为空
    17. MultiTreeNode() {}
    18. MultiTreeNode(int x) : val(x) {}
    19. };
    20. class MultiTree {
    21. public:
    22. //输入连通的无向图的邻接表,构造一棵多叉生成树,val存放原id
    23. static MultiTreeNode* edgesToMultiTree(map<int, vector<int>>&m)
    24. {
    25. map<int, int>visit;
    26. map<int, MultiTreeNode*>mt;
    27. int x = m.begin()->first;
    28. queue<int>q;
    29. q.push(x);
    30. visit[x] = 1;
    31. mt[x] = new MultiTreeNode(x);
    32. while (!q.empty()) {
    33. int id = q.front();
    34. q.pop();
    35. for (auto x : m[id]) {
    36. if (visit[x])continue;
    37. q.push(x);
    38. visit[x] = 1;
    39. mt[id]->son.push_back(mt[x] = new MultiTreeNode(x));
    40. }
    41. }
    42. return mt[x];
    43. }
    44. };
    45. //把二叉树或多叉树转成id形式的树,前序遍历,从0开始编号
    46. class TreeWithId
    47. {
    48. public:
    49. unordered_map<int, vector<int>>sons;//所有子节点的编号,其中根节点编号=0
    50. unordered_map<int, int>vals;//节点权值
    51. TreeWithId(TreeNode* root) {
    52. if (root)dfs(root);
    53. }
    54. TreeWithId(MultiTreeNode* root) {
    55. if (root)dfs(root);
    56. }
    57. unordered_mapint>m;//原指针对应在新树中的编号
    58. unordered_mapint>m2;
    59. private:
    60. inline void dfs(TreeNode* root) {
    61. if (m.find(root) == m.end())m[root] = m.size();
    62. vals[m[root]] = root->val;
    63. if (root->left)dfs(root->left), sons[m[root]].push_back(m[root->left]);
    64. if (root->right)dfs(root->right), sons[m[root]].push_back(m[root->right]);
    65. }
    66. inline void dfs(MultiTreeNode* root) {
    67. if (m2.find(root) == m2.end())m2[root] = m2.size();
    68. vals[m2[root]] = root->val;
    69. for (auto p : root->son)dfs(p), sons[m2[root]].push_back(m2[p]);
    70. }
    71. };
    72. //type=1是求最小值,=2是求最大值, =3是minId,=4是maxId
    73. template<int type, typename T = int>
    74. class RMQ
    75. {
    76. public:
    77. RMQ() {}
    78. RMQ(const vector& data) {
    79. this->data = data;
    80. len = data.size();
    81. logLen = getLength(len + 5);
    82. init(data);
    83. }
    84. inline T getMinMax(int low, int high) { //求[low,high]内的最值,0<=low<=high
    85. if (low == high)return v[low][0];
    86. int j = getLength(high - low) - 1;
    87. return opt(v[high + 1 - (1 << j)][j], v[low][j]);
    88. }
    89. inline int getMinMaxId(int low, int high) { //求[low,high]内的最值的id,0<=low<=high
    90. if (low == high)return v[low][0];
    91. int j = getLength(high - low) - 1;
    92. return optId(v[high + 1 - (1 << j)][j], v[low][j]);
    93. }
    94. private:
    95. void init(const vector& data) {
    96. v.resize(len);
    97. for (int i = 0; i < v.size(); i++) {
    98. v[i].resize(logLen);
    99. if (type <= 2)v[i][0] = data[i];
    100. else v[i][0] = i;
    101. }
    102. for (int j = 1; j < logLen; j++)
    103. {
    104. for (int i = 0; i < len; i++)
    105. {
    106. v[i][j] = v[i][j - 1];
    107. int k = i + (1 << (j - 1));
    108. if (k >= len)continue;
    109. if (type <= 2) v[i][j] = opt(v[i][j], v[k][j - 1]);
    110. else v[i][j] = optId(v[i][j], v[k][j - 1]);
    111. }
    112. }
    113. }
    114. static inline T opt(T x, T y) {
    115. return type == 1 ? min(x, y) : max(x, y);
    116. }
    117. inline T optId(int x, int y) {
    118. if (type == 3) {
    119. return data[x] < data[y] ? x : y;
    120. }
    121. return data[x] < data[y] ? y : x;
    122. }
    123. //二进制总位数
    124. static inline int getLength(int n) {
    125. int ans = 0;
    126. while (n)
    127. {
    128. n >>= 1;
    129. ans++;
    130. }
    131. return ans;
    132. }
    133. private:
    134. vectordata;
    135. vector>v;
    136. int len, logLen;
    137. };
    138. class LCA {
    139. public:
    140. LCA(TreeWithId tree) {
    141. int n = tree.vals.size();
    142. visitn.resize(n);
    143. visitDeep.resize(n * 2 - 1);
    144. ids.resize(n * 2 - 1);
    145. dfs(tree, 0, 1);
    146. opt = RMQ<3>(visitDeep);
    147. }
    148. //输入2个节点的id,输出最近公共祖先的id
    149. int getLca(int x, int y)
    150. {
    151. x = visitn[x], y = visitn[y];
    152. if (x > y)x ^= y ^= x ^= y;
    153. int minId = opt.getMinMaxId(x, y); //求最小深度对应的遍历数
    154. return ids[minId];
    155. }
    156. private:
    157. void dfs(TreeWithId& tree, int k, int d)
    158. {
    159. for (auto p : tree.sons[k])
    160. {
    161. visitDeep[vnum] = d;
    162. ids[vnum++] = k;
    163. dfs(tree, p, d + 1);
    164. }
    165. visitn[k] = vnum; //存入每个点的任意一个遍历数
    166. visitDeep[vnum] = d; //存入遍历数对应的深度
    167. ids[vnum++] = k; //存入遍历数对应的节点id
    168. }
    169. vector<int> visitDeep;
    170. vector<int> visitn;
    171. vector<int> ids;
    172. int vnum = 0;
    173. RMQ<3>opt;
    174. };

    2,测试代码

    1. bool test3() //待完善
    2. {
    3. TreeNode* root = new TreeNode(0);
    4. TreeWithId tree{ root };
    5. RMQ<1>{};
    6. LCA lca(tree);
    7. return true;
    8. }
    9. int main()
    10. {
    11. if (test3())cout << "test succ!";
    12. return 0;
    13. }

    四,DancingLink、Covering

    1,代码

    1. class DancingLink // 精确覆盖算法
    2. {
    3. public:
    4. DancingLink(int m, int n, int maxNum) //01矩阵的行、列、1的最大数量
    5. {
    6. this->m = m, this->n = n, maxNum += n + 1;
    7. rhead.resize(m + 1), nums.resize(n + 1);
    8. row.resize(maxNum), col.resize(maxNum);
    9. up.resize(maxNum), down.resize(maxNum), lef.resize(maxNum), rig.resize(maxNum);
    10. sc.resize(m), rows.resize(m);
    11. for (int i = 0; i <= n; i++)
    12. {
    13. up[i] = i, down[i] = i;
    14. lef[i] = i - 1, rig[i] = i + 1;
    15. row[i] = 0, col[i] = i, nums[i] = 0;
    16. }
    17. lef[0] = n, rig[n] = 0, nums[0] = INT_MAX;
    18. key = n;
    19. for (int i = 0; i <= m; i++)rhead[i] = 0;
    20. }
    21. void push(int r, int c)//新增坐标在(r,c)的一个节点
    22. {
    23. row[++key] = r, col[key] = c;
    24. up[key] = c, down[key] = down[c];
    25. up[down[c]] = key, down[c] = key;
    26. if (rhead[r] == 0)rhead[r] = lef[key] = rig[key] = key;
    27. else
    28. {
    29. lef[key] = rhead[r], rig[key] = rig[rhead[r]];
    30. lef[rig[rhead[r]]] = key, rig[rhead[r]] = key;
    31. }
    32. nums[c]++;
    33. }
    34. vectorint>> getAllAns()
    35. {
    36. return dfs(false);
    37. }
    38. vector<int> getAnyAns()
    39. {
    40. auto v = dfs(true);
    41. if (v.size())return v[0];
    42. return vector<int>{};
    43. }
    44. private:
    45. vectorint>> dfs(bool onlyOne)
    46. {
    47. vectorint>>ans;
    48. while (true) {
    49. if (rig[0] == 0) {
    50. rows.resize(rowsid);
    51. ans.push_back(rows);
    52. rows.resize(m);
    53. if (onlyOne)return ans;
    54. }
    55. int c = min_element(nums.begin() + 1, nums.end()) - nums.begin();
    56. if (rig[0] == 0)c = 0;
    57. del(c);
    58. while (true) {
    59. c = down[c];
    60. if (c > n)break;
    61. reback(col[c]);
    62. if (scid == 0)return ans;
    63. c = sc[--scid];
    64. rowsid--;
    65. for (int j = rig[c]; j != c; j = rig[j])reback(col[j]);
    66. }
    67. sc[scid++] = c;//记录选中id
    68. rows[rowsid++] = row[c];
    69. for (int j = rig[c]; j != c; j = rig[j])del(col[j]);
    70. }
    71. return ans;
    72. }
    73. inline void del(int c)//删除第c列的所有元素和他们所在行的所有元素
    74. {
    75. lef[rig[c]] = lef[c], rig[lef[c]] = rig[c];
    76. for (int i = down[c]; i != c; i = down[i])
    77. for (int j = rig[i]; j != i; j = rig[j])
    78. down[up[j]] = down[j], up[down[j]] = up[j], nums[col[j]]--;
    79. nums[c] = INT_MAX;
    80. }
    81. inline void reback(int c)//完全回退del操作
    82. {
    83. lef[rig[c]] = rig[lef[c]] = c, nums[c] = 0;
    84. for (int i = down[c]; i != c; i = down[i]) {
    85. for (int j = rig[i]; j != i; j = rig[j])
    86. down[up[j]] = up[down[j]] = j, nums[col[j]]++;
    87. nums[c]++;
    88. }
    89. }
    90. private:
    91. int m, n, key;
    92. vector<int>row, col;//每个节点的行,列
    93. vector<int>rhead;//每行第一个节点的id
    94. vector<int>up, down, lef, rig;//每个节点上下左右的节点id
    95. vector<int>nums;//每一列的元素个数
    96. vector<int>sc;
    97. int scid = 0, rowsid = 0;
    98. vector<int>rows;//覆盖选中的行,值的范围是从1到m
    99. };
    100. #ifndef struct_UndirectedEdge
    101. #define struct_UndirectedEdge
    102. template<typename T = int>
    103. struct UndirectedEdge
    104. {
    105. UndirectedEdge() {
    106. a = b = dist = 0;
    107. };
    108. UndirectedEdge(const vector<int>&v) {
    109. a = v[0], b = v[1], dist = 0;
    110. if (v.size() > 2)dist = v[2];
    111. }
    112. int a;//端点a的id
    113. int b;//端点b的id
    114. T dist;//ab之间的距离
    115. };
    116. #endif
    117. class Covering {
    118. public:
    119. //给定一个2n个点的图,选出n条边,刚好覆盖这2n个点,返回所有的解
    120. static vectorint>>> getEdgeCover(int n, vectorint>> &v)
    121. {
    122. DancingLink d(v.size(), n * 2, v.size() * 2);
    123. for (int i = 0; i < v.size(); i++) {
    124. d.push(i, v[i].a + 1);
    125. d.push(i, v[i].b + 1);
    126. }
    127. vectorint>>>ans;
    128. vectorint>> vrow = d.getAllAns();
    129. for (auto vi : vrow) {
    130. vectorint>>vans; //getNumFromId(v, vi)
    131. transform(vi.begin(), vi.end(), std::back_inserter(vans), [&](int id) {return v[id]; });
    132. ans.push_back(vans);
    133. }
    134. return ans;
    135. }
    136. };

    2,测试代码

    1. bool testDancingLink()//待完善
    2. {
    3. return true;
    4. }
    5. bool testCovering()//待完善
    6. {
    7. return true;
    8. }
    9. int main()
    10. {
    11. if (testDancingLink() && testCovering())cout << "test succ!";
    12. return 0;
    13. }

    五,并查集、无向图、最小生成树Kruskal

    1,代码

    1. class Union //并查集
    2. {
    3. public:
    4. Union(int num, bool canZip = true, int startId = 0) //startId一般是0或1,可以大于1,不能太大
    5. {
    6. fa.resize(num + startId);
    7. for (int i = startId; i < fa.size(); i++)fa[i] = i;
    8. this->canZip = canZip;
    9. this->startId = startId;
    10. }
    11. virtual int find(int x) //找祖先,canZip控制能否做路径压缩加速
    12. {
    13. if (canZip) {
    14. if (fa[x] == x)return x;
    15. return fa[x] = find(fa[x]);
    16. }
    17. int r = x;
    18. while (fa[r] != r)r = fa[r];
    19. return r;
    20. }
    21. bool inSame(int x, int y)//是否位于同一个集合
    22. {
    23. return find(x) == find(y);
    24. }
    25. void merge(int x, int y)//合并2个集合,如果是同一个集合则不做操作
    26. {
    27. if (!inSame(x, y))fa[find(x)] = y;
    28. }
    29. vector<int> getRoots()//获取所有根节点
    30. {
    31. vector<int>ans;
    32. ans.reserve(fa.size());
    33. for (int i = startId; i < fa.size(); i++)if (fa[i] == i)ans.push_back(i);
    34. return ans;
    35. }
    36. int getRootNums()//统计根节点数目
    37. {
    38. return getRoots().size();
    39. }
    40. vectorint>> getGroups()
    41. {
    42. vector<int> roots = getRoots();
    43. map<int, int>m = reflect(roots);
    44. vectorint>>ans(m.size());
    45. for (int i = startId; i < fa.size(); i++)ans[m[find(i)]].push_back(i);
    46. return ans;
    47. }
    48. protected:
    49. template<typename T>
    50. mapint> reflect(const vector& v)
    51. {
    52. mapint>m;
    53. for (int i = 0; i < v.size(); i++)m[v[i]] = i;
    54. return m;
    55. }
    56. protected:
    57. vector<int>fa;
    58. bool canZip;
    59. int startId;
    60. };
    61. class UnionDif :public Union //差分版并查集,依赖路径压缩
    62. {
    63. public:
    64. UnionDif(int num, int startId = 0) :Union{ num,true,startId } {}
    65. int find(int x) //找祖先
    66. {
    67. if (fa[x] == x)return x;
    68. find(fa[x]);
    69. dif[x] += dif[fa[x]];
    70. fa[x] = fa[fa[x]];
    71. return fa[x];
    72. }
    73. void merge(int x, int y, double xSubY = 0)//合并2个集合,如果是同一个集合则不做操作
    74. {
    75. if (inSame(x, y))return;
    76. find(x);
    77. dif[fa[x]] = xSubY - dif[x];
    78. fa[fa[x]] = y;
    79. return;
    80. }
    81. double getDif(int x)
    82. {
    83. return dif[x];
    84. }
    85. private:
    86. map<int, double>dif;//每个节点和fa的差分
    87. };
    88. template<typename T>
    89. class Vunion:public Union //集合并查集
    90. {
    91. public:
    92. Vunion(int num) :Union{ num } {};
    93. void push(vector>&v) {
    94. mapint>>m;
    95. for (int i = 0; i < v.size(); i++)for (auto x : v[i])m[x].push_back(i);
    96. for (auto &p : m) {
    97. for (auto x : p.second)merge(x, p.second[0]);
    98. }
    99. }
    100. };
    101. #ifdef LOCAL
    102. #ifndef struct_TreeNode
    103. #define struct_TreeNode
    104. struct TreeNode {
    105. int val;
    106. TreeNode* left;
    107. TreeNode* right;
    108. TreeNode() : val(0), left(nullptr), right(nullptr) {}
    109. TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    110. TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
    111. };
    112. #endif
    113. #endif
    114. #ifndef struct_UndirectedEdge
    115. #define struct_UndirectedEdge
    116. template<typename T = int>
    117. struct UndirectedEdge
    118. {
    119. UndirectedEdge() {
    120. a = b = dist = 0;
    121. };
    122. UndirectedEdge(const vector<int>&v) {
    123. a = v[0], b = v[1], dist = 0;
    124. if (v.size() > 2)dist = v[2];
    125. }
    126. int a;//端点a的id
    127. int b;//端点b的id
    128. T dist;//ab之间的距离
    129. };
    130. #endif
    131. template<typename T = int>
    132. struct UndirectedGraphData
    133. {
    134. public:
    135. vector>edges; //边集,无法表示孤立点,一条边只出现一次
    136. mapint, int>, T>edgeMap; //边集,无法表示孤立点,一条边出现两次
    137. map<int, vector<int>>adjaList;//邻接表,孤立点是否出现取决于allPointFlag,一条边两个点都出现在对方的邻接表中
    138. bool allPointFlag = false;//默认邻接表中不含孤立点
    139. int startId = 0;
    140. public:
    141. UndirectedGraphData() {
    142. }
    143. UndirectedGraphData(const vector>&edges) {
    144. this->edges = edges;
    145. adjaList = undirectedEdgeToAdjaList(edges);
    146. edgeMap = undirectedEdgeToValueMap(edges);
    147. }
    148. UndirectedGraphData( vectorint>>& edges) { //仅限没有权值或者权值为整数的图
    149. transform(edges.begin(), edges.end(), std::back_inserter(this->edges), [](const vector<int>& v) {return UndirectedEdge<int>{v}; });
    150. adjaList = undirectedEdgeToAdjaList(this->edges);
    151. edgeMap = undirectedEdgeToValueMap(this->edges);
    152. }
    153. UndirectedGraphData(const map<int, vector<int>>& adjaList) { //仅限没有权值的图
    154. this->adjaList = adjaList;
    155. for (auto& v : this->adjaList) {
    156. for (auto vi : v.second)if (v.first < vi)edges.push_back(UndirectedEdge(vector<int>{v.first, vi, 0}));
    157. }
    158. edgeMap = undirectedEdgeToValueMap(edges);
    159. }
    160. void setNumV(int n, int startId = 0) { //startId一般是0或1,可以大于1
    161. allPointFlag = true;
    162. for (int i = startId; i < startId + n; i++)adjaList[i];
    163. this->startId = startId;
    164. }
    165. int getNumV() const {
    166. return adjaList.size();
    167. }
    168. int getNumE() const {
    169. return edges.size();
    170. }
    171. private:
    172. //输入无向边集{{1,2}{1,3}{2,3}},输出邻接表{1:{2,3},2:{1,3},3:{1,2}}
    173. static map<int, vector<int>> undirectedEdgeToAdjaList(const vector>& v)
    174. {
    175. map<int, vector<int>> ans;
    176. for (auto& vi : v) {
    177. ans[vi.a].push_back(vi.b);
    178. ans[vi.b].push_back(vi.a);
    179. }
    180. return ans;
    181. }
    182. //输入无向带权边集,输出边和权的映射
    183. static mapint, int>, T> undirectedEdgeToValueMap(const vector>& v)
    184. {
    185. mapint, int>, T>m;
    186. for (auto& vi : v) {
    187. m[{vi.a, vi.b}] = vi.dist;
    188. m[{vi.b, vi.a}] = vi.dist;
    189. }
    190. return m;
    191. }
    192. };
    193. class UndirectedGraph
    194. {
    195. public:
    196. //输入二叉树的边集,生成任意一棵二叉树,val存放原id
    197. static TreeNode* edgesToBinaryTree(vectorint>>& edges)
    198. {
    199. map<int, int>ids;
    200. for (auto &e : edges) {
    201. for (int i = 0; i <= 1; i++) {
    202. if (ids.find(e[i]) == ids.end())ids[e[i]] = ids.size();
    203. }
    204. }
    205. map<int, vector<int>>m;
    206. Union un(ids.size());
    207. for (auto &e : edges) {
    208. int id0 = ids[e[0]], id1 = ids[e[1]];
    209. if (!un.inSame(id0, id1)) {
    210. un.merge(id0, id1);
    211. m[e[0]].push_back(e[1]);
    212. m[e[1]].push_back(e[0]);
    213. }
    214. }
    215. int id = -12345;
    216. for (auto &mi : m)if (mi.second.size() < 3) {
    217. id = mi.first;
    218. break;
    219. }
    220. if (id == -12345)return nullptr;
    221. map<int, int>visit;
    222. TreeNode* ans = new TreeNode(id);
    223. queueq;
    224. q.push(ans);
    225. while (!q.empty()) {
    226. TreeNode* p = q.front();
    227. q.pop();
    228. visit[p->val] = 1;
    229. for (auto x : m[p->val])if (visit[x] == 0) {
    230. TreeNode* p2 = new TreeNode(x);
    231. q.push(p2);
    232. if (!p->left)p->left = p2;
    233. else p->right = p2;
    234. }
    235. }
    236. return ans;
    237. }
    238. //无向拓扑排序,输入无向无环图{{1,2}{1,3}{4,3}}的邻接表和指定根1,输出父节点表{4:3, 3:1, 2:1}
    239. static map<int, int> undirectedEdgeToFatherList(UndirectedGraphData<int> &g, int root)
    240. {
    241. auto& m = g.adjaList;
    242. map<int, int>visit;
    243. map<int, int>fa;
    244. queue<int>q;
    245. q.push(root);
    246. visit[root] = 1;
    247. while (!q.empty()) {
    248. int id = q.front();
    249. q.pop();
    250. for (auto c : m[id]) {
    251. if (visit[c] == 0)q.push(c), fa[c] = id;
    252. visit[c] = 1;
    253. }
    254. }
    255. return fa;
    256. }
    257. //根据无向图的邻接表判断是否有环
    258. static bool hasUndirectedCircle(const UndirectedGraphData<int>& g)
    259. {
    260. auto& m = g.adjaList;
    261. vector<int>keys; //auto keys = getFirst(m);
    262. transform(m.begin(), m.end(), std::back_inserter(keys), [](const pair<int, vector<int>>& p) {return p.first; });
    263. int minkey = *min_element(keys.begin(), keys.end());
    264. int maxKey = *max_element(keys.begin(), keys.end());
    265. Union unions(maxKey - minkey + 1);
    266. mapint, int>, int>mp;
    267. for (auto& mi : m) {
    268. for (auto k : mi.second) {
    269. if (mp[make_pair(k, mi.first)])continue;
    270. if (unions.inSame(k - minkey, mi.first - minkey))return true;
    271. unions.merge(k - minkey, mi.first - minkey);
    272. mp[make_pair(mi.first, k)] = 1;
    273. }
    274. }
    275. return false;
    276. }
    277. //判断是不是k-正则图
    278. static bool isCompleteGraph(int k, UndirectedGraphData<int> &g)
    279. {
    280. for (auto &mi : g.adjaList) {
    281. if (mi.second.size() != k)return false;
    282. }
    283. return true;
    284. }
    285. //判断是不是二分图, 节点编号是0到n-1
    286. static bool isTwoDivGraph(int n, UndirectedGraphData<int> &g) {
    287. UnionDif unions(n);
    288. for (auto e : g.edges) {
    289. unions.find(e.a);
    290. unions.find(e.b);
    291. if (unions.inSame(e.a, e.b)) {
    292. if (int(unions.getDif(e.a) + unions.getDif(e.b)) % 2)return false;
    293. }
    294. else {
    295. unions.merge(e.a, e.b, 1);
    296. }
    297. }
    298. return true;
    299. }
    300. };
    301. class Kruskal
    302. {
    303. public:
    304. //计算最小生成树,结果按照边从小到大排序,出参treeNum是森林中树的数量
    305. static vectorint>> kruskalMinCostTree(int n, vectorint>>& v, int& treeNum)
    306. {
    307. sort(v.begin(), v.end(), cmp);
    308. Union unions(n);
    309. vectorint>>ans;
    310. for (int i = 0, j = 0; j < n - 1 && i < v.size(); i++)
    311. {
    312. if (unions.inSame(v[i].a, v[i].b))continue;
    313. unions.merge(v[i].a, v[i].b);
    314. ans.push_back(v[i]);
    315. j++;
    316. }
    317. treeNum = unions.getRootNums();
    318. return ans;
    319. }
    320. private:
    321. static bool cmp(UndirectedEdge<int>& a, UndirectedEdge<int>& b)
    322. {
    323. return a.dist < b.dist;
    324. }
    325. };

    2,测试代码

    1. template<typename T>
    2. static bool vecIsSame(const vector& v1, const vector& v2)
    3. {
    4. if (v1.size() - v2.size())return false;
    5. for (int i = 0; i < v1.size(); i++)if (v1[i] != v2[i])return false;
    6. return true;
    7. }
    8. #define EXPECT_VEC_EQ(a,b) if(!vecIsSame((a),(b))){cout<<"ERROR!!!!!!!!!\n";return false;}
    9. bool testUnion()
    10. {
    11. Union u(5);
    12. EXPECT_VEC_EQ(u.getRoots(), (vector<int>{0, 1, 2, 3, 4}));
    13. u.merge(1, 2);
    14. u.merge(1, 1);
    15. u.merge(3, 3);
    16. EXPECT_VEC_EQ(u.getRoots(), (vector<int>{0, 2, 3, 4}));
    17. u.merge(4, 3);
    18. auto v = u.getRoots();
    19. EXPECT_VEC_EQ(u.getRoots(), (vector<int>{0, 2, 3}));
    20. return true;
    21. }
    22. bool testUndirectedGraph()//待完善
    23. {
    24. return true;
    25. }
    26. bool testKruskal()//待完善
    27. {
    28. Kruskal{};
    29. return true;
    30. }
    31. bool test4()
    32. {
    33. return testUnion() && testUndirectedGraph() && testKruskal();
    34. }
    35. int main()
    36. {
    37. if (test4())cout << "test succ!";
    38. return 0;
    39. }

    六,最小生成树Prim

    1,代码

    1. class Prim
    2. {
    3. public:
    4. //计算最小生成树,结果按照边从小到大排序
    5. static vectorint, int>> minCostConnectPoints(int n, mapint, int>, int>& value)
    6. {
    7. vector<bool>visit_(n);
    8. vector<int>minLen(n);
    9. for (int i = 0; i < n; i++) {
    10. minLen[i] = INT_MAX;
    11. visit_[i] = false;
    12. }
    13. minLen[getStartId(n, value)] = INT_MIN;
    14. vectorint, int>>ans;
    15. for (int i = 0; i < n; i++) {
    16. int id = getId(n, visit_, minLen);
    17. for (int j = 0; j < n; j++) {
    18. if (visit_[j] && value[make_pair(id, j)] == minLen[id]) {
    19. ans.push_back(make_pair(id, j));
    20. break;
    21. }
    22. }
    23. visit_[id] = true;
    24. fresh(n, visit_, minLen, value, id);
    25. }
    26. return ans;
    27. }
    28. private:
    29. static int getStartId(int n, mapint, int>, int>& value)
    30. {
    31. int m = INT_MAX;
    32. int ans = 0;
    33. for (int i = 0; i < n; i++) {
    34. for (int j = 0; j < n; j++) {
    35. if (i != j && m > value[make_pair(i, j)]) {
    36. m = value[make_pair(i, j)];
    37. ans = i;
    38. }
    39. }
    40. }
    41. return ans;
    42. }
    43. static int getId(int n, vector<bool>& visit_, vector<int>& minLen)
    44. {
    45. int m = INT_MAX;
    46. int ans = 0;
    47. for (int i = 0; i < n; i++) {
    48. if (!visit_[i] && m > minLen[i]) {
    49. m = minLen[i];
    50. ans = i;
    51. }
    52. }
    53. return ans;
    54. }
    55. static void fresh(int n, vector<bool>& visit_, vector<int>& minLen, mapint, int>, int>& value, int id)
    56. {
    57. for (int i = 0; i < n; i++) {
    58. if (!visit_[i])minLen[i] = min(minLen[i], value[make_pair(i, id)]);
    59. }
    60. }
    61. };

    2,测试代码

    1. bool testPrim()//待完善
    2. {
    3. Prim{};
    4. return true;
    5. }
    6. int main()
    7. {
    8. if (testPrim())cout << "test succ!";
    9. return 0;
    10. }

    七,有向图、单源最短路径、连通分量、拓扑排序

    1,代码

    1. template<typename T = int>
    2. struct DirectedEdge
    3. {
    4. DirectedEdge() {
    5. a = b = dist = 0;
    6. };
    7. DirectedEdge(const vector<int>&v) {
    8. a = v[0], b = v[1], dist = v[2];
    9. }
    10. int a;//端点a的id
    11. int b;//端点b的id
    12. T dist;//从a到b的距离
    13. };
    14. template<typename T = int>
    15. struct DirectedGraphData
    16. {
    17. public:
    18. vector>edges; //边集,无法表示孤立点
    19. mapint, int>, T>edgeMap; //边集,无法表示孤立点
    20. map<int, vector<int>>adjaList;//邻接表,孤立点是否出现取决于allPointFlag
    21. bool allPointFlag = false;//默认邻接表中不含孤立点
    22. int startId = 0;
    23. public:
    24. DirectedGraphData(){
    25. }
    26. DirectedGraphData(const vector>& edges) {
    27. this->edges = edges;
    28. adjaList = directedEdgeToAdjaList(edges);
    29. edgeMap = directedEdgeToValueMap(edges);
    30. }
    31. DirectedGraphData(const vectorint>>& edges) { //仅限权值为整数的图
    32. transform(edges.begin(), edges.end(), std::back_inserter(this->edges), [](const vector<int>& v) {return DirectedEdge<int>{v}; });
    33. adjaList = directedEdgeToAdjaList(this->edges);
    34. edgeMap = directedEdgeToValueMap(this->edges);
    35. }
    36. DirectedGraphData(map<int, vector<int>>& adjaList) { //仅限没有权值的图
    37. this->adjaList = adjaList;
    38. for (auto& v : adjaList) {
    39. for (auto vi : v.second)edges.push_back(DirectedEdge({v.first, vi, 0}));
    40. }
    41. edgeMap = directedEdgeToValueMap(edges);
    42. }
    43. void setNumV(int n, int startId = 0) { //startId一般是0或1,可以大于1
    44. allPointFlag = true;
    45. for (int i = startId; i < startId + n; i++)adjaList[i];
    46. this->startId = startId;
    47. }
    48. int getNumV() const {
    49. return adjaList.size();
    50. }
    51. int getNumE() const {
    52. return edges.size();
    53. }
    54. private:
    55. //输入有向边集{{1,2}{1,3}{2,3}},输出邻接表{1:{2,3},2:{3}}
    56. static map<int, vector<int>> directedEdgeToAdjaList(const vector>& v)
    57. {
    58. map<int, vector<int>> ans;
    59. for (auto& vi : v) {
    60. ans[vi.a].push_back(vi.b);
    61. ans[vi.b];
    62. }
    63. return ans;
    64. }
    65. //输入有向带权边集,输出边和权的映射
    66. static mapint, int>, int> directedEdgeToValueMap(const vector>& v)
    67. {
    68. mapint, int>, int>m;
    69. for (auto& vi : v) {
    70. m[{vi.a, vi.b}] = vi.dist;
    71. }
    72. return m;
    73. }
    74. };
    75. class DirectedGraph
    76. {
    77. public:
    78. //构建有向图的反向图
    79. static map<int, vector<int>> reverseGraph(const DirectedGraphData<int> &g)
    80. {
    81. auto& m = g.adjaList;
    82. map<int, vector<int>> ans;
    83. for (auto& mi : m) {
    84. for (auto& k : mi.second)ans[k].push_back(mi.first);
    85. }
    86. return ans;
    87. }
    88. //求有向无环图中的最长路径长度,出参nextNode是每个点的后继,len是每个点出发的最长路径长度
    89. static int getLongestPath(map<int, vector<int>>& m, map<int, int>& nextNode, map<int, int>& len)
    90. {
    91. int ans = 0;
    92. for (auto& ai : m)ans = max(ans, dp(m, nextNode, len, ai.first));
    93. return ans;
    94. }
    95. //判断是否有环
    96. static bool hasCircle(int numCourses, map<int, vector<int>>& m)
    97. {
    98. map<int, int>visitt;//单次访问标记
    99. map<int, int>flag;//所有访问标记
    100. for (int i = 0; i < numCourses; i++)
    101. {
    102. if (flag[i])continue;
    103. if (!canFinish(m, i, visitt, flag))return true;
    104. }
    105. return false;
    106. }
    107. private:
    108. static int dp(map<int, vector<int>>& m, map<int, int>& nextNode, map<int, int>& len, int id)
    109. {
    110. if (len[id])return len[id];
    111. len[id] = 1, nextNode[id] = -1; //无后继的则是 - 1
    112. for (auto k : m[id]) {
    113. if (len[id] < dp(m, nextNode, len, k) + 1) {
    114. len[id] = dp(m, nextNode, len, k) + 1;
    115. nextNode[id] = k;
    116. }
    117. }
    118. return len[id];
    119. }
    120. static bool canFinish(map<int, vector<int>>& m, int loc, map<int, int>& visitt, map<int, int>& flag) {
    121. if (visitt[loc] == 1)return false;
    122. if (flag[loc] == 1)return true;
    123. visitt[loc] = 1, flag[loc] = 1;
    124. for (int k : m[loc])if (!canFinish(m, k, visitt, flag))return false;
    125. visitt[loc] = 0;
    126. return true;
    127. }
    128. };
    129. class Dijskra//求最短路,适用于不存在负权值的边的图
    130. {
    131. public:
    132. static map<int, int> shortestPath(map<int, vector<int>>& m, mapint, int>, int>& value, int n, int src)
    133. {
    134. map<int, int>dis;
    135. priority_queue< Node, vector< Node>, cmp>que;
    136. map<int, int>visit;
    137. for (int i = 0; i < n; i++)dis[i] = INT_MAX;
    138. que.push({ src,0 });
    139. dis[src] = 0;
    140. while (!que.empty())
    141. {
    142. Node nod = que.top();
    143. que.pop();
    144. if (visit[nod.id])continue;
    145. visit[nod.id] = 1;
    146. for (auto& vi : m[nod.id]) {
    147. if (nod.len + value[{nod.id, vi}] < dis[vi]) {
    148. que.push({ vi, dis[vi] = nod.len + value[{nod.id, vi}] });
    149. }
    150. }
    151. }
    152. return dis;
    153. }
    154. private:
    155. struct Node
    156. {
    157. int id;
    158. int len;
    159. };
    160. class cmp
    161. {
    162. public:
    163. bool operator()(Node a, Node b)
    164. {
    165. return a.len > b.len;
    166. }
    167. };
    168. };
    169. class BellmanFord //求最短路,适用于不存在负权值的环的图
    170. {
    171. public:
    172. static map<int, int> shortestPath(const DirectedGraphData<int>& g, int src)
    173. {
    174. map<int, int>dis;
    175. int n = g.getNumV();
    176. for (int i = 0; i < n; i++)dis[i] = INT_MAX;
    177. dis[src] = 0;
    178. for (int i = 0; i < n; i++) {
    179. if (!refresh(g.edgeMap, dis))break;
    180. if (i == n - 1)return map<int, int>{}; //有负环
    181. }
    182. return dis;
    183. }
    184. private:
    185. static inline bool refresh(const mapint, int>, int>& value, map<int, int>&dis)
    186. {
    187. bool flag = false;
    188. auto dis2 = dis;
    189. for (auto& e : value) {
    190. if (dis2[e.first.second] > ((long long)dis[e.first.first]) + e.second) {
    191. dis2[e.first.second] = ((long long)dis[e.first.first]) + e.second, flag = true;
    192. }
    193. }
    194. dis = dis2;
    195. return flag;
    196. }
    197. };
    198. class SPFA //求最短路,适用于不存在负权值的环的图
    199. {
    200. public:
    201. static map<int, int> shortestPath(const DirectedGraphData<int>& g, int src)
    202. {
    203. map<int, int>dis;
    204. map<int, bool>inQueue;
    205. map<int, int>visit;
    206. int n = g.getNumV();
    207. for (int i = 0; i < n; i++)dis[i] = INT_MAX;
    208. dis[src] = 0;
    209. queue<int>q;
    210. q.push(src);
    211. visit[src]++;
    212. inQueue[src] = true;
    213. while (!q.empty()) {
    214. int t = q.front();
    215. q.pop();
    216. inQueue[t] = false;
    217. auto v = refresh(dis, t, g);
    218. for (auto vi : v) {
    219. if (inQueue[vi])continue;
    220. q.push(vi);
    221. inQueue[vi] = true;
    222. if (++visit[vi] >= n)return map<int, int>{};//存在负环
    223. }
    224. }
    225. return dis;
    226. }
    227. private:
    228. static inline vector<int> refresh(map<int, int>&dis, int t, const DirectedGraphData<int>& g)
    229. {
    230. vector<int>ans;
    231. auto it = g.adjaList.find(t);
    232. if (it == g.adjaList.end())return ans;
    233. long long d = dis[t];
    234. for (auto vi : it->second) {
    235. if (dis[vi] > d + g.edgeMap.at(make_pair(t, vi))) {
    236. dis[vi] = d + g.edgeMap.at(make_pair(t, vi));
    237. ans.push_back(vi);
    238. }
    239. }
    240. return ans;
    241. }
    242. };
    243. //不区分有向图和无向图的通用操作
    244. class GraphOpt
    245. {
    246. public:
    247. //根据点集取子图,输入邻接表,输出邻接表
    248. static map<int, vector<int>> getSubGraph(map<int, vector<int>>& m, vector<int>& v)
    249. {
    250. map<int, vector<int>>ans;
    251. map<int, int>mv;
    252. for (auto vi : v)mv[vi] = 1;
    253. for (auto vi : v) {
    254. for (auto mi : m[vi]) {
    255. if (mv[mi])ans[vi].push_back(mi);
    256. }
    257. }
    258. return ans;
    259. }
    260. };
    261. class SemiConnect
    262. {
    263. public:
    264. //半连通分量分割
    265. static vectorint>> semiConnectComponent(map<int, vector<int>>& m)
    266. {
    267. vectorint>>allans;
    268. map<int, int>visit;
    269. for (auto& mi : m) {
    270. int k = mi.first;
    271. if (visit[k])continue;
    272. vector<int>ans;
    273. DFS(m, visit, k, ans);
    274. allans.push_back(ans);
    275. }
    276. return allans;
    277. }
    278. protected:
    279. //DFS从k开始遍历,记录所有节点最后一次访问的顺序的反序
    280. static void DFS(map<int, vector<int>>& m, map<int, int>& visit, int k, vector<int>& ans)
    281. {
    282. if (visit[k])return;
    283. visit[k] = 1;
    284. for (auto i : m[k])DFS(m, visit, i, ans);
    285. ans.insert(ans.begin(), k);
    286. }
    287. };
    288. class KosarajuStrongConnect :public DirectedGraph, public GraphOpt, public SemiConnect
    289. {
    290. public:
    291. //Kosaraju算法,强连通分量分割
    292. static vectorint>> connectComponent(map<int, vector<int>>& m)
    293. {
    294. vectorint>> semi = semiConnectComponent(m);
    295. auto m2 = reverseGraph(m);
    296. vectorint>>allans;
    297. map<int, int>visit;
    298. for (auto& s : semi) {
    299. auto m3 = getSubGraph(m2, s);
    300. for (auto& k : s) {
    301. if (visit[k])continue;
    302. vector<int>ans;
    303. DFS(m3, visit, k, ans);
    304. allans.push_back(ans);
    305. }
    306. }
    307. return allans;
    308. }
    309. //强连通分量缩点,输入强连通分量列表,输出缩点后的邻接表
    310. static map<int, vector<int>> getPointGraph(vectorint>>&v, map<int, vector<int>>&m)
    311. {
    312. map<int, int>g;
    313. map<int, vector<int>>ans;
    314. for (int i = 0; i < v.size(); i++)for (auto x : v[i])g[x] = i;
    315. for (auto &mi : m) {
    316. for (auto x : mi.second)
    317. if (g[x] != g[mi.first])
    318. ans[mi.first].push_back(x);
    319. }
    320. return ans;
    321. }
    322. };
    323. class TarjanDoubledirect
    324. {
    325. public:
    326. vectorint, int>>cutb;//割边
    327. vector<int>cutv;//割点
    328. vectorint>>conv;//点双连通分量的点集
    329. vectorlong long>>convb;//点双连通分量的边集
    330. int cons = 0;//无向连通分量数目
    331. TarjanDoubledirect(int n, map<int, vector<int>>& m)
    332. {
    333. this->n = n;
    334. this->m = m;
    335. visit.resize(n);
    336. added.resize(n);
    337. dfn.resize(n);
    338. low.resize(n);
    339. for (int i = 0; i < n; i++)if (!visit[i]) {
    340. root = i;
    341. dfs(i);
    342. cons++;
    343. }
    344. FillConv();
    345. }
    346. private:
    347. void dfs(int k)
    348. {
    349. visit[k] = true;
    350. low[k] = dfn[k] = dfnId++;
    351. bool cv = false;
    352. int chNum = 0;
    353. st.push(k);
    354. for (auto nk : m[k]) {
    355. if (isBackB(nk))low[k] = min(low[k], dfn[nk]);
    356. if (visit[nk])continue;
    357. chNum++;
    358. sFa.push(k);
    359. dfs(nk);
    360. sFa.pop();
    361. low[k] = min(low[k], low[nk]);
    362. vector<int>conv1;
    363. vector<long long>convb1;
    364. if (low[nk] >= dfn[k]) {
    365. cv = true;
    366. for (int time = INT_MAX; time; time--) {
    367. if (st.top() == nk)time = 1;
    368. conv1.push_back(st.top());
    369. added[st.top()] = true;
    370. for (auto i : m[st.top()])if (!added[i])convb1.push_back((long long)(st.top()) * n + i);
    371. st.pop();
    372. }
    373. if (conv1.size() > 1) {
    374. conv1.push_back(k);
    375. conv.push_back(conv1);
    376. convb.push_back(convb1);
    377. }
    378. }
    379. if (low[nk] >= dfn[nk])cutb.push_back(make_pair(k, nk));
    380. }
    381. if ((k != root && cv && chNum > 0) || (k == root && chNum > 1))cutv.push_back(k);
    382. }
    383. bool isBackB(int nk) // 判断从k到nk是不是后向边
    384. {
    385. return visit[nk] && (sFa.empty() || nk != sFa.top());//如果st.top()是nk,则是树边,不是后向边
    386. }
    387. void FillConv()//补充由单点组成的点连通分量
    388. {
    389. map<int, int>m;
    390. for (auto& ci : conv) {
    391. for (auto& k : ci)m[k] = 1;
    392. }
    393. vector<int>conv1(1);
    394. for (int i = 0; i < n; i++)if (m[i] == 0) {
    395. conv1[0] = i;
    396. conv.push_back(conv1);
    397. convb.push_back(vector<long long>());
    398. }
    399. }
    400. int n;
    401. int dfnId = 0;
    402. int root;
    403. vector<bool>visit;//DFS访问标记
    404. vector<bool>added;
    405. vector<int>dfn;//首次访问的次序
    406. vector<int>low;//通过一条后向边能达到的最小dfn
    407. map<int, vector<int>> m;//邻接表
    408. stack<int>sFa;//用于判断父节点
    409. stack<int>st;
    410. };
    411. class TarjanStrongConnect
    412. {
    413. public:
    414. vectorint>>conv;//强连通分量的点集
    415. TarjanStrongConnect(int n, map<int, vector<int>>& m)
    416. {
    417. this->n = n;
    418. this->m = m;
    419. visit.resize(n);
    420. added.resize(n);
    421. dfn.resize(n);
    422. low.resize(n);
    423. for (int i = 0; i < n; i++)if (!visit[i]) {
    424. root = i;
    425. dfs(i);
    426. }
    427. FillConv();
    428. }
    429. private:
    430. void dfs(int k)
    431. {
    432. visit[k] = true;
    433. low[k] = dfn[k] = dfnId++;
    434. bool cv = false;
    435. int chNum = 0;
    436. st.push(k);
    437. for (auto nk : m[k]) {
    438. if (isBackB(nk))low[k] = min(low[k], dfn[nk]);
    439. if (visit[nk])continue;
    440. chNum++;
    441. dfs(nk);
    442. low[k] = min(low[k], low[nk]);
    443. }
    444. vector<int>conv1;
    445. vector<long long>convb1;
    446. if (low[k] >= dfn[k]) {
    447. cv = true;
    448. for (int time = INT_MAX; time; time--) {
    449. if (st.top() == k)time = 1;
    450. conv1.push_back(st.top());
    451. added[st.top()] = true;
    452. st.pop();
    453. }
    454. conv.push_back(conv1);
    455. }
    456. }
    457. bool isBackB(int nk) // 判断从k到nk是不是后向边
    458. {
    459. return visit[nk] && !added[nk];
    460. }
    461. void FillConv()//补充由单点组成的点连通分量
    462. {
    463. map<int, int>m;
    464. for (auto& ci : conv) {
    465. for (auto& k : ci)m[k] = 1;
    466. }
    467. vector<int>conv1(1);
    468. for (int i = 0; i < n; i++)if (m[i] == 0) {
    469. conv1[0] = i;
    470. conv.push_back(conv1);
    471. }
    472. }
    473. int n;
    474. int dfnId = 0;
    475. int root;
    476. vector<bool>visit;//DFS访问标记
    477. vector<bool>added;
    478. vector<int>dfn;//首次访问的次序
    479. vector<int>low;//通过一条后向边能达到的最小dfn
    480. map<int, vector<int>> m;//邻接表
    481. stack<int>st;
    482. };
    483. //有向图拓扑排序
    484. class DirectedTopoSort:public KosarajuStrongConnect
    485. {
    486. public:
    487. //有向无环图拓扑排序,输入n=3,g.edges={{0,1}{0,2}{1,2}}, 输出{0,1,2},有环则输出为空
    488. static vector<int> topoSortNoCircle(int n, DirectedGraphData<int>& g)
    489. {
    490. auto& v = g.edges;
    491. priority_queue<int, vector<int>, greater<int>> q;
    492. map<int, int>m;
    493. for (auto &vi : v)m[vi.b]++;
    494. for (int i = 0; i < n; i++)if (m[i] == 0)q.push(i);
    495. vector<int>ans;
    496. auto &mv = g.adjaList;
    497. while (!q.empty()) {
    498. int k = q.top();
    499. q.pop();
    500. ans.push_back(k);
    501. for (auto i : mv[k]) {
    502. m[i]--;
    503. if (m[i] == 0)q.push(i);
    504. }
    505. }
    506. return ans.size() == n ? ans : vector<int>{};
    507. }
    508. //有向图拓扑排序
    509. static vectorint>> topoSort(DirectedGraphData<int>& g)
    510. {
    511. vectorint>> con = connectComponent(g.adjaList);
    512. map<int, vector<int>> pointGraph = getPointGraph(con, g.adjaList);
    513. DirectedGraphData<int>ga(pointGraph);
    514. vector<int> vp = topoSortNoCircle(con.size(), ga);
    515. vectorint>>ans;
    516. for (auto id : vp)ans.push_back(con[id]);
    517. return ans;
    518. }
    519. };

    2,测试代码

    1. bool testDirectedGraph()//待完善
    2. {
    3. DirectedGraph{};
    4. return true;
    5. }
    6. bool testDijskra()//待完善
    7. {
    8. map<int, vector<int>> m;
    9. mapint, int>, int> value;
    10. int n = 1;
    11. DijskraShortestPath(m, value, n, 0);
    12. return true;
    13. }
    14. bool testBellmanFord()//待完善
    15. {
    16. return true;
    17. }
    18. bool testGraphOpt()//待完善
    19. {
    20. GraphOpt{};
    21. return true;
    22. }
    23. bool testConnect()//待完善
    24. {
    25. SemiConnect{};
    26. KosarajuStrongConnect{};
    27. int n = 1;
    28. map<int, vector<int>> m;
    29. TarjanDoubledirect{ n,m };
    30. TarjanStrongConnect{ n,m };
    31. return true;
    32. }
    33. bool testTopoSort() //待完善
    34. {
    35. map<int, vector<int>>m;
    36. m[1].push_back(2);
    37. m[2].push_back(3);
    38. m[3].push_back(1);
    39. m[3].push_back(4);
    40. m[4].push_back(5);
    41. m[5].push_back(6);
    42. m[6].push_back(4);
    43. m[5].push_back(7);
    44. DirectedGraphData<int>g(m);
    45. auto ans = DirectedTopoSort::topoSort(g);
    46. return true;
    47. }
    48. bool test5()
    49. {
    50. return testDirectedGraph() && testDijskra() && testBellmanFord() && testGraphOpt() && testConnect() && testTopoSort();
    51. }
    52. int main()
    53. {
    54. if (test5())cout << "test succ!";
    55. return 0;
    56. }

    八,网格图、回路链路、路径重建

    1,代码

    1. class GridGraph
    2. {
    3. public:
    4. GridGraph(int row, int col)
    5. {
    6. this->row = row;
    7. this->col = col;
    8. initD4D8();
    9. }
    10. int gridId(int r, int c) //阅读顺序的id,先给col赋值再调用
    11. {
    12. return r * col + c;
    13. }
    14. vector<int> getNeighbor4(int k)//获得四邻居的id
    15. {
    16. vector<int>ans;
    17. for (int i = 0; i < 4; i++) {
    18. if (inBoard(k / col + dx4[i], k % col + dy4[i]))ans.push_back(k + d4[i]);
    19. }
    20. return ans;
    21. }
    22. vector<int> getNeighbor8(int k)//获得八邻居的id
    23. {
    24. vector<int>ans;
    25. for (int i = 0; i < 8; i++) {
    26. if (inBoard(k / col + dx8[i], k % col + dy8[i]))ans.push_back(k + d8[i]);
    27. }
    28. return ans;
    29. }
    30. private:
    31. int row;
    32. int col;
    33. //二维坐标系的邻居偏移量
    34. const vector<int> dx4{ 0,0,1,-1 };
    35. const vector<int> dy4{ 1,-1,0,0 };
    36. const vector<int> dx8{ 0,0,1,-1,1,1,-1,-1 };
    37. const vector<int> dy8{ 1,-1,0,0 ,1,-1,1,-1 };
    38. //一维id坐标系的邻居偏移量
    39. vector<int> d4;
    40. vector<int> d8;
    41. private:
    42. inline void initD4D8()
    43. {
    44. for (int i = 0; i < 4; i++)d4.push_back(gridId(dx4[i], dy4[i]));
    45. for (int i = 0; i < 8; i++)d8.push_back(gridId(dx8[i], dy8[i]));
    46. }
    47. inline bool inBoard(int r, int c)
    48. {
    49. return r >= 0 && r < row&& c >= 0 && c < col;
    50. }
    51. inline bool inBoard(int id)
    52. {
    53. return id >= 0 && inBoard(id / col, id % col);
    54. }
    55. };
    56. class Hierholzer {
    57. public:
    58. stack<int>euler;//欧拉回路或链路,栈顶是起点
    59. Hierholzer(int n, map<int, vector<int>>& m, int type, int start = 0)//type=0是无向图 1是有向图
    60. {
    61. this->n = n;
    62. this->m = m;
    63. this->type = type;
    64. dfs(GetStartPoint(start));
    65. }
    66. private:
    67. int GetStartPoint(int start)//链路是唯一起点,回路是指定起点
    68. {
    69. if (type == 0) {
    70. for (auto& mi : m) {
    71. if (mi.second.size() % 2)return mi.first;
    72. for (auto nk : mi.second)num[id(mi.first, nk)]++;
    73. }
    74. for (auto& ni : num)ni.second /= 2;
    75. }
    76. else {
    77. map<int, int>m2;
    78. for (auto& mi : m)for (auto nk : mi.second)m2[nk]++, num[id(mi.first, nk)]++;
    79. for (auto& mi : m)if (mi.second.size() > m2[mi.first])return mi.first;
    80. }
    81. return start;
    82. }
    83. void dfs(int k)
    84. {
    85. while (true) {
    86. while (mid[k] < m[k].size()) {
    87. if (num[id(k, m[k][mid[k]])]-- <= 0)mid[k]++;
    88. else sdfs.push(k), k = m[k][mid[k]];
    89. }
    90. euler.push(k);
    91. if (sdfs.empty()) return;
    92. k = sdfs.top(), sdfs.pop();
    93. }
    94. }
    95. inline long long id(int a, int b)
    96. {
    97. if (type == 0 && a > b)a ^= b ^= a ^= b;
    98. return (long long)a * n + b;
    99. }
    100. int n;
    101. int type;
    102. stack<int>sdfs;
    103. map<int, vector<int>> m;//邻接表
    104. map<int, int>mid;
    105. map<long long, int>num;//支持多重边
    106. };
    107. class Hamilton
    108. {
    109. public:
    110. stack<int> hami;//哈密顿链路
    111. Hamilton(int n, map<int, vector<int>>& m, int type)//type=0是无向图 1是有向图
    112. {
    113. this->n = n;
    114. this->m = m;
    115. this->type = type;
    116. for (int i = 0; i < n; i++)dfs(i);
    117. }
    118. private:
    119. bool dfs(int k)
    120. {
    121. s.push(k);
    122. if (s.size() == n) {
    123. hami = s;
    124. return true;
    125. }
    126. for (auto nk : m[k]) {
    127. if (visit[k])continue;
    128. visit[k] = 1;
    129. if (dfs(nk))return true;
    130. visit[k] = 0;
    131. }
    132. s.pop();
    133. return false;
    134. }
    135. int n;
    136. int type;
    137. map<int, vector<int>> m;//邻接表
    138. map<int, int>visit;
    139. stack<int>s;
    140. };
    141. class ReBuild
    142. {
    143. public:
    144. stack<int> ans;
    145. ReBuild(map<int, int>& dis, map<int, vector<int>>& m, int col, int s, int e)
    146. {
    147. this->e = e;
    148. this->col = col;
    149. ans.push(e);
    150. dfs(dis, m, s);
    151. }
    152. private:
    153. bool dfs(map<int, int>& dis, map<int, vector<int>>& m, int k)
    154. {
    155. if (k == e)return true;
    156. for (int nex : m[k]) {
    157. if (dis[nex] == dis[k] + len(k, nex) && dfs(dis, m, nex)) {
    158. ans.push(k);
    159. return true;
    160. }
    161. }
    162. return false;
    163. }
    164. int len(int s, int e)
    165. {
    166. if (s / col == e / col)return abs(s - e);
    167. return abs(s - e) / col;
    168. }
    169. int col;
    170. int e;
    171. };

    2,测试代码

    1. bool testGridGraph()//待完善
    2. {
    3. GridGraph{ 0, 0 };
    4. return true;
    5. }
    6. bool testHierholzerAndHamilton()//待完善
    7. {
    8. map<int, vector<int>> m;
    9. mapint, int>, int> value;
    10. int n = 1;
    11. Hierholzer{ n,m,0,0 };
    12. Hamilton{ n,m,0 };
    13. return true;
    14. }
    15. bool testReBuild()//待完善
    16. {
    17. map<int, vector<int>> m;
    18. map<int, int> dis;
    19. ReBuild{ dis,m,0,0,0 };
    20. return true;
    21. }
    22. bool test6()
    23. {
    24. return testGridGraph() && testHierholzerAndHamilton() && testReBuild();
    25. }
    26. int main()
    27. {
    28. if (test6())cout << "test succ!";
    29. return 0;
    30. }

  • 相关阅读:
    什么是redis,redis能做什么,redis的应用场景
    C++ Reference: Standard C++ Library reference: Containers: array: array: end
    CMT2380F32模块开发17-ADC例程
    6.19-MyBatis源码—体系介绍和配置文件解析源码剖析
    百度一面:谈谈 @Transactional 的原理和坑
    LQ0159 无穷分数【计算精度】
    Redis数据类型
    LeetCode每日一题(1573. Number of Ways to Split a String)
    中国金控盐碱地水稻 国稻种芯-林裕豪:粮食安全两会热点
    MongoDB数据库一篇全解
  • 原文地址:https://blog.csdn.net/nameofcsdn/article/details/132857972