代码随想录算法训练营第58天 | 并查集应用类
108.冗余连接
https://kamacoder.com/problempage.php?pid=1181
代码随想录
https://www.programmercarl.com/kamacoder/0108.冗余连接.html#思路
108.冗余连接
-
在加入边之前;判断是否在一个集合;如果不在一个集合内,加入边;如果在一个集合内,就不加入(否则就会出现环)
-
建立类 直接调用类
点击查看代码
class unionfind: def __init__(self,size): self.root = [i for i in range(size)] def find(self,u): if u != self.root[u]: self.root[u] = self.find(self.root[u]) return self.root[u] def join(self,u,v): u = self.find(u) v = self.find(v) if u==v: return self.root[v] = u def issame(self,u,v): u = self.find(u) v = self.find(v) return u==v def main(): n = int(input()) uf = unionfind(n+1) for _ in range(n): s,t = map(int,input().split()) if uf.issame(s,t): print(str(s)+" "+str(t)) else: uf.join(s,t) if __name__ == '__main__': main()
109.冗余连接2
- 入度为2的节点
- 情况一:两个边都能删除 删除顺序靠后的边;
- 情况二:需要判断哪一条边
- 删一条边后是否是有向树
- 没有入度为2的点 说明图中已经有环:删掉构成环的边
- 步骤:
- 输入边 收集对应的入度个数
- 如果找到为2的边:反向
- 判断删除哪条边:如果删除该边有环 则返回false
- 如果没有入度为2的边 遍历每条边 找到环则删除
点击查看代码
class unionfind: def __init__(self,size): self.root = [i for i in range(size)] def find(self,u): if u != self.root[u]: self.root[u] = self.find(self.root[u]) return self.root[u] def join(self,u,v): u = self.find(u) v = self.find(v) if u==v: return self.root[v] = u def issame(self,u,v): u = self.find(u) v = self.find(v) return u==v def getremove(edges): uf = unionfind(len(edges)+1) for i in edges: if uf.issame(i[0],i[1]): print(str(i[0])+" "+str(i[1])) return else: uf.join(i[0],i[1]) def istreeafterremove(edges,delete): uf = unionfind(len(edges)+1) for i in range(len(edges)): if i==delete: continue if uf.issame(edges[i][0],edges[i][1]): return False uf.join(edges[i][0],edges[i][1]) return True def main(): n = int(input()) indegree = [0]*(n+1) edges = [] for _ in range(n): s,t = map(int,input().split()) edges.append([s,t]) indegree[t]+=1 vec = [] for i in range(n-1,-1,-1): if indegree[edges[i][1]]==2: vec.append(i) if len(vec)>0: if istreeafterremove(edges,vec[0]): print(str(edges[vec[0]][0])+" "+str(edges[vec[0]][1])) else: print(str(edges[vec[1]][0])+" "+str(edges[vec[1]][1])) return else: getremove(edges) if __name__ == '__main__': main()
- 入度为2的节点