classUnionFind{public:UnionFind(intn):id(n){iota(begin(id),end(id),0);}boolunion_(intu,intv){constinti=find(u);constintj=find(v);if(i==j)returnfalse;id[i]=j;returntrue;}private:vector<int>id;intfind(intu){returnid[u]==u?u:id[u]=find(id[u]);}};classSolution{public:vector<int>findRedundantDirectedConnection(vector<vector<int>>&edges){vector<int>ids(edges.size()+1);intnodeWithTwoParents=0;for(constvector<int>&e:edges){constintv=e[1];if(++ids[v]==2){nodeWithTwoParents=v;break;}}// If there is no edge with two ids// We don't have to skip any edgeif(nodeWithTwoParents==0)returnfindRedundantDirectedConnection(edges,-1);for(inti=edges.size()-1;i>=0;--i)if(edges[i][1]==nodeWithTwoParents)// Try to delete edges[i]if(findRedundantDirectedConnection(edges,i).empty())returnedges[i];throw;}vector<int>findRedundantDirectedConnection(constvector<vector<int>>&edges,intskippedEdgeIndex){UnionFinduf(edges.size()+1);for(inti=0;i<edges.size();++i){if(i==skippedEdgeIndex)continue;if(!uf.union_(edges[i][0],edges[i][1]))returnedges[i];}return{};}};
classUnionFind{publicUnionFind(intn){id=newint[n];for(inti=0;i<n;++i)id[i]=i;}publicbooleanunion(intu,intv){finalinti=find(u);finalintj=find(v);if(i==j)returnfalse;id[i]=j;returntrue;}privateint[]id;privateintfind(intu){returnid[u]==u?u:(id[u]=find(id[u]));}}classSolution{publicint[]findRedundantDirectedConnection(int[][]edges){int[]ids=newint[edges.length+1];intnodeWithTwoParents=0;for(int[]e:edges){finalintv=e[1];if(++ids[v]==2){nodeWithTwoParents=v;break;}}// If there is no edge with two ids// We don't have to skip any edgeif(nodeWithTwoParents==0)returnfindRedundantDirectedConnection(edges,-1);for(inti=edges.length-1;i>=0;--i)if(edges[i][1]==nodeWithTwoParents)// Try to delete edges[i]if(findRedundantDirectedConnection(edges,i).length==0)returnedges[i];thrownewIllegalArgumentException();}privateint[]findRedundantDirectedConnection(int[][]edges,intskippedEdgeIndex){UnionFinduf=newUnionFind(edges.length+1);for(inti=0;i<edges.length;++i){if(i==skippedEdgeIndex)continue;if(!uf.union(edges[i][0],edges[i][1]))returnedges[i];}returnnewint[]{};}}
classUnionFind:def__init__(self,n:int):self.id=[iforiinrange(n+1)]defunion(self,u:int,v:int)->bool:i=self.find(u)j=self.find(v)ifi==j:returnFalseself.id[i]=jreturnTruedeffind(self,u:int)->int:ifself.id[u]!=u:self.id[u]=self.find(self.id[u])returnself.id[u]classSolution:deffindRedundantDirectedConnection(self,edges:List[List[int]])->List[int]:ids=[0]*(len(edges)+1)nodeWithTwoParents=0foru,vinedges:ids[v]+=1ifids[v]==2:nodeWithTwoParents=vdeffindRedundantDirectedConnection(skippedEdgeIndex:int)->List[int]:uf=UnionFind(len(edges)+1)fori,edgeinenumerate(edges):ifi==skippedEdgeIndex:continueifnotuf.union(edge[0],edge[1]):returnedgereturn[]# If there is no edge with two ids# We don't have to skip any edgeifnodeWithTwoParents==0:returnfindRedundantDirectedConnection(-1)foriinreversed(range(len(edges))):_,v=edges[i]ifv==nodeWithTwoParents:# Try to delete edges[i]ifnotfindRedundantDirectedConnection(i):returnedges[i]