• 代码随想录算法训练营Day62|冗余连接、冗余连接II


    冗余连接

    108. 冗余连接 (kamacoder.com)

    考虑使用并查集,逐次将s、t加入并查集中,当发现并查集中find(u)和find(v)相同时,输出u和v,表示删除的边即可。

    1. #include
    2. #include
    3. using namespace std;
    4. // 定义一个函数find,用于在并查集中找到元素u的根节点
    5. int find(const vector<int>& check, int u) {
    6. if (u == check[u]) // 如果u是其自身的根,则返回u
    7. return u;
    8. else // 否则递归地查找u的根
    9. return find(check, check[u]);
    10. }
    11. // 定义一个函数join,用于合并两个集合
    12. void join(vector<int>& check, int u, int v) {
    13. int n = find(check, u); // 找到u的根
    14. int m = find(check, v); // 找到v的根
    15. if (n == m) { // 如果两个根相同,说明加入边(u,v)会形成环
    16. cout << u << " " << v; // 输出这条边
    17. }
    18. check[m] = n; // 将v的根设置为u,实现集合的合并
    19. }
    20. int main() {
    21. int N;
    22. cin >> N; // 输入节点数和边数
    23. vector<int> check(N + 1, 0); // 初始化并查集数组
    24. for (int i = 0; i <= N; i++) {
    25. check[i] = i; // 每个元素的根初始化为自己
    26. }
    27. int s, t;
    28. for (int i = 0; i < N; i++) {
    29. cin >> s >> t; // 输入一条边的两个节点
    30. join(check, s, t); // 将两个节点合并到同一个集合中
    31. }
    32. return 0;
    33. }

    时间复杂度为O(N),空间复杂度为O(N)。

    冗余连接II

    109. 冗余连接II (kamacoder.com)

    代码随想录 (programmercarl.com)

    本题本质为:一个有向图是由一颗有向树和一条有向边组成,我们需要找到并删除那条边。

    此外,“若有多条边可以删除,请输出标准输入中最后出现的一条边”,说明在两条边都可以删除的情况下,要删除顺序靠后的边。

    对于一颗有向树而言,根节点入度为0,其余节点入度为1。

    因此对应的删除有三种情况:

    1.有一点入度为2,删除指向该节点的一条边

    3的入度为2,删除1->3或2->3。

    2.入度为2,但只能删除特定边。

    此处3的入度为2,但删除4->3明显无济于事,因此在找到入度为2的点还需判断删除哪条边会使图成为有向树。

    3没有入度为2的点,有环

    只需删掉构成环的靠后的边即可。

    贴一下代码随想录的代码:

    1. #include
    2. #include
    3. using namespace std;
    4. int n;
    5. vector<int> father (1001, 0);
    6. // 并查集初始化
    7. void init() {
    8. for (int i = 1; i <= n; ++i) {
    9. father[i] = i;
    10. }
    11. }
    12. // 并查集里寻根的过程
    13. int find(int u) {
    14. return u == father[u] ? u : father[u] = find(father[u]);
    15. }
    16. // 将v->u 这条边加入并查集
    17. void join(int u, int v) {
    18. u = find(u);
    19. v = find(v);
    20. if (u == v) return ;
    21. father[v] = u;
    22. }
    23. // 判断 u 和 v是否找到同一个根
    24. bool same(int u, int v) {
    25. u = find(u);
    26. v = find(v);
    27. return u == v;
    28. }
    29. // 在有向图里找到删除的那条边,使其变成树
    30. void getRemoveEdge(const vectorint>>& edges) {
    31. init(); // 初始化并查集
    32. for (int i = 0; i < n; i++) { // 遍历所有的边
    33. if (same(edges[i][0], edges[i][1])) { // 构成有向环了,就是要删除的边
    34. cout << edges[i][0] << " " << edges[i][1];
    35. return;
    36. } else {
    37. join(edges[i][0], edges[i][1]);
    38. }
    39. }
    40. }
    41. // 删一条边之后判断是不是树
    42. bool isTreeAfterRemoveEdge(const vectorint>>& edges, int deleteEdge) {
    43. init(); // 初始化并查集
    44. for (int i = 0; i < n; i++) {
    45. if (i == deleteEdge) continue;
    46. if (same(edges[i][0], edges[i][1])) { // 构成有向环了,一定不是树
    47. return false;
    48. }
    49. join(edges[i][0], edges[i][1]);
    50. }
    51. return true;
    52. }
    53. int main() {
    54. int s, t;
    55. vectorint>> edges;
    56. cin >> n;
    57. vector<int> inDegree(n + 1, 0); // 记录节点入度
    58. for (int i = 0; i < n; i++) {
    59. cin >> s >> t;
    60. inDegree[t]++;
    61. edges.push_back({s, t});
    62. }
    63. vector<int> vec; // 记录入度为2的边(如果有的话就两条边)
    64. // 找入度为2的节点所对应的边,注意要倒序,因为优先删除最后出现的一条边
    65. for (int i = n - 1; i >= 0; i--) {
    66. if (inDegree[edges[i][1]] == 2) {
    67. vec.push_back(i);
    68. }
    69. }
    70. if (vec.size() > 0) {
    71. // 放在vec里的边已经按照倒叙放的,所以这里就优先删vec[0]这条边
    72. if (isTreeAfterRemoveEdge(edges, vec[0])) {
    73. cout << edges[vec[0]][0] << " " << edges[vec[0]][1];
    74. } else {
    75. cout << edges[vec[1]][0] << " " << edges[vec[1]][1];
    76. }
    77. return 0;
    78. }
    79. // 处理情况三
    80. // 明确没有入度为2的情况,那么一定有有向环,找到构成环的边返回就可以了
    81. getRemoveEdge(edges);
    82. }

    算法的时间复杂度和空间复杂度为O(N)。

  • 相关阅读:
    阿里云+作业帮+小红书:论剑云原生时代的 SRE与智能运维
    我的CS Master毕业之路|猿创征文
    mac使用n切换node版本
    【计算机网络--物理层】编码和调制与数据交换方式
    [论文笔记] Balboa: Bobbing and Weaving around Network Censorship
    shell_41.Linux获取所有的数据
    EasyWeChat6.x生成小程序码, JSON 数据时遇到了非法的 UTF-8 字符序列
    什么是内容运营?
    HCI 解决方案对比:Harvester 和 OpenStack
    新零售电商O2O模式解析
  • 原文地址:https://blog.csdn.net/github_35852648/article/details/140269995