LintCode 图是否是树 并查集
题目: 原题地址
给出 n
个节点,标号分别从 0
到 n - 1
并且给出一个 无向
边的列表 (给出每条边的两个顶点), 写一个函数去判断这张`无向`图是否是一棵树
注意事项
你可以假设我们不会给出重复的边在边的列表当中. 无向
边 [0, 1]
和 [1, 0]
是同一条边, 因此他们不会同时出现在我们给你的边的列表当中
样例
给出n = 5
并且 edges = [[0, 1], [0, 2], [0, 3], [1, 4]]
, 返回 true.
给出n = 5
并且 edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]]
, 返回 false.
刚开始看到题目时,想用并查集做,然后看到标签,它写是DFS。
但我觉得这种类型的题目,并查集会好很多,于是就有了下面的代码。
思路:
构建多个单向的树,用一个father数组来维护他们各各节点的关系。如果出现冲突(如A->B,C->B.这里B的父亲有两个,但由于题目中的关系是无向的,这种关系其实是A-B,C-B,也就是说可以看成A->B->C),因此先用一个list,将这些冲突的边记录下来,然后在将他们变换成无冲突的关系。
之后再通过并查集查找所有节点是否已联通,即是否会有孤立的节点。
若全部节点都联通了,而且不会有成环的情况,那就是一颗树了返回true。否则就不是,返回false
具体注释写在代码里了:
public boolean validTree(int n, int[][] edges) { int[] tem = new int[n];//用于记录并查集过程中,走过的节点,避免重复查 int[] father = new int[n];//用于维护节点的父关系 for (int i = 0; i < n; i++) { father[i] = i;//初始化,默认为自己,即没有父节点 } List<int[]> list = new ArrayList<int[]>();//用于存储那些会冲突的节点 for (int i = 0; i < edges.length; i++) { int f = edges[i][0];//默认以前一个位置为父关系节点 int s = edges[i][1];//默认以后一个位置为子关系节点 if (father[s] == s) { father[s] = f;//维护关系 } else { list.add(edges[i]);//冲突后,即子节点已经有父节点了,将这个关系先存起来 } } for (int[] e : list) {//遍历之前存起来的冲突,然后依依解决它 int f = e[0];//父节点 int s = e[1];//子节点 int sf = find(father, s,tem);//查找子节点的最高父节点 int ff = find(father, f,tem);//查找父节点的最高父节点 if (sf == -1 || ff == -1)//如果出现==-1,则表示并查集中出现了环,给的关系为图。返回false return false; if (sf == ff)//如果出现两节点的最高父节点一样,则表是,该冲突关系最终会成环,无法解决冲突,给的关系为图,返回false return false; else father[ff] = sf;//解决冲突,将他们连起来 } int find = find(father, 0, tem);//找第一个点的最高父节点 for (int i = 1; i < n; i++) { if (find != find(father, i, tem)) {//依次与第一个节点的最高父节点比较,看是否会出现孤立的节点,出现的那么就构不成树,返回false return false; } } return true; } /** * 并查集 * @param father * @param f * @param tem * @return */ private int find(int[] father, int f, int[] tem) { Arrays.fill(tem, 0);//将标记清空 /** * 找到f节点的最高父节点 */ int j = f; while (j != father[j]) { if (tem[j] != 0) return -1;//表示这个过程中,成环了 tem[j] = 1; j = father[j]; } /** * 路径压缩,加快下一次查找时的效率 */ int i = f, k; while (i != j) { k = father[i]; father[i] = j; i = k; } return j;//返回找到的最高节点 }
最后附上一张AC图~