冗余链接
题目链接:https://leetcode-cn.com/problems/redundant-connection/
题目描述:
在本问题中, 树指的是一个连通且无环的无向图。 输入一个图,该图由一个有着N个节点 (节点值不重复1, 2, ..., N) 的树及一条附加的边构成。附加的边的两个顶点包含在1到N中间,这条附加的边不属于树中已存在的边。 结果图是一个以边组成的二维数组。每一个边的元素是一对[u, v] ,满足 u < v,表示连接顶点u 和v的无向图的边。 返回一条可以删去的边,使得结果图是一个有着N个节点的树。如果有多个答案,则返回二维数组中最后出现的边。答案边 [u, v] 应满足相同的格式 u < v。
示例:
示例 1: 输入: [[1,2], [1,3], [2,3]] 输出: [2,3] 解释: 给定的无向图为: 1 / \ 2 - 3 示例 2: 输入: [[1,2], [2,3], [3,4], [1,4], [1,5]] 输出: [1,4] 解释: 给定的无向图为: 5 - 1 - 2 | | 4 - 3
题目分析:
分析题目,题目要求本质是要输出那些让生成树成环的线,故使用查并集求解。
查并集:
定义一个parent数组用于存放每个节点的根节点。再连结两点之前先通过自定义的find函数找出两节点的根节点。
若根节点相同,则这一条线必定能够让原先的生成树成环
若根节点不相同,则不成环,并使两线根节点相连。
优化:
定义一个rank数组,表示该点到根节点的长度。
为了防止生成树退化成链式结构,可以通过分析rank数组判断如何相接!
源码:
#include<iostream> #include<vector> #include<cstring> using namespace std; int parent[1005]; int rank1[1005]; int find(int i)//查 { while (parent[i] != -1) i = parent[i]; return i; } int main() { memset(parent, -1, sizeof(parent)); memset(rank1, 0, sizeof(rank1)); vector<vector<int>>edges = { {1, 4 }, {3, 4}, {1, 3}, { 1, 2 }, { 4, 5 } }; int ans[2] = { 0 }; for (int i = 0;i < edges.size();i++)//并 { int root1 = find(edges[i][0]); int root2 = find(edges[i][1]); if (root1 == root2) { ans[0] = edges[i][0]; ans[1] = edges[i][1]; } else { if (rank1[root1] > rank1[root2]) parent[root2] = root1; else if(rank1[root1] < rank1[root2]) parent[root1] = root2; else { parent[root2] = root1; rank1[root2]++; } } } cout << ans[0] << " " << ans[1]; } /* { {1,2 }, { 1, 3 }, { 2, 3 } }; [2,3] { {1,2 }, { 2,3 }, { 3,4 }, { 1,4 }, { 1,5 } }; [1,4] { {1, 3}, {3, 4}, {1, 5}, {3, 5}, {2, 3} }; [3,5] { {1, 4 }, {3, 4}, {1, 3}, { 1, 2 }, { 4, 5 } }; [1,3] */