-
树可以看成是一个连通且 无环 的 无向 图。
-
给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1 到 n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 ai 和 bi 之间存在一条边。
-
请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的边。
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
};
并查集
- 若图中存在环,则一定会在检测到某条边的时候,发现它关联的两个顶点早已属于同一个集合。
- 分析:不断将新的边加入并查集,如果出现 (uf.find(item[0]) == uf.find(item[1])),则新的边item就是冗余的。
class UnionFind:
# n为节点大小
def __init__(self, n):
self.fa = list(range(n)) # 从0开始 祖先结点
print(self.fa)
# 查找(递归)
def find(self, val):
if self.fa[val] == val:
return val
else:
return self.find(self.fa[val])
# 查找 祖先节点 (递归,路径压缩)
def fastfind(self, val):
if self.fa[val] == val:
return val
else:
self.fa[val] = self.find(self.fa[val])# 路径压缩
return self.find(self.fa[val])
# 连接
def merge(self, x, y):
fa_x = self.find(x)
fa_y = self.find(y)
self.fa[fa_y] = fa_x
class Solution:
def findRedundantConnection(self,edges:list[list[int]])->list[int]:
uf = UnionFind(len(edges)+1)// 3+1 ,0节点与其他节点独立存在
for item in edges:
if uf.find(item[0]) == uf.find(item[1]):
return item
else:
uf.merge(item[0],item[1])
if __name__ == "__main__":
print ('Hello World')
print(Solution().findRedundantConnection([[1,2], [1,3], [2,3]]))
/******************************************************************************
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, Java, PHP, Ruby, Perl,
C#, OCaml, VB, Swift, Pascal, Fortran, Haskell, Objective-C, Assembly, HTML, CSS, JS, SQLite, Prolog.
Code, Compile, Run and Debug online from anywhere in world.
*******************************************************************************/
#include <iostream>
#include<vector>
#include<memory>
using namespace std;
class Solution {
public:
vector<int> fa;//并查集矩阵
int find(int val){
if (fa[val] == val){//当前为祖先节点,直接返回
return val;
}else{
return find(fa[val]);//否则寻找父节点的祖先节点
}
return 0;
}
void merge(int x,int y){//在并查集中合并节点
int fa_x = find(x);
int fa_y = find(y);
fa[fa_x] = fa_y;
}
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
fa.reserve(edges.size()+1);
for(int i=0;i<edges.size()+1;i++){//初始化
fa[i] = i;
}
for(auto v: edges){
if(find(v[0]) == find(v[1])){// 如果两个节点的祖先相同,则它们已经在一个树上,不能在作为新的添加节点
return v;
}else{
merge(v[0],v[1]);//否则讲两个融合
}
}
return {0,0};
}
};
int main()
{
unique_ptr<Solution> mysolo = unique_ptr<Solution>(new Solution());
cout<<"Hello World"<<endl;
vector< vector<int> >edge = {{1,2},{1,3},{2,3}};
vector<int> res = mysolo->findRedundantConnection(edge);
for(auto v: res){
cout<<v<<"-->";
}
return 0;
}
dfs遍历方法
- 遍历并记录当前的图中是否出现环
- 好像要多次遍历图才行,一般地遍历方法如下
无向图环路判断
- next != pre 让环路向下延伸,如果在环路一直向下延伸的情况下,还遇到了访问过的节点,那么此无向图中存在环路
bool dfs(int cur, int pre,int next ){
if( visit[cur]){ return true}// 有环路
visit[cur]= true;
if(next != pre){
for( int v: g[cur]){
dfs(v,cur,v);
}
}
}
- 正确代码
bool dfs(int cur, int pre ){
if( visit[cur]){ return true}// 有环路
visit[cur]= true;
for( int next: g[cur]){
if(next != pre){
bool subcondition = dfs(next,cur);
if (subcondition){ return true;}
}
}
return false; // 如果遍历了所有后续节点,没有返回true,返回当前是非环路的
}
//测试代码
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
vector<vector<int>> g;
vector<int> visit(4);
bool dfs(int cur, int pre ,vector<vector<int>> g){
if( visit[cur]){ return true;}// 有环路
visit[cur]= true;
for( int next: g[cur]){
if(next != pre){
bool subcondition = dfs(next,cur,g);
if (subcondition){ return true;}
}
}
return false; // 如果遍历了所有后续节点,没有返回true,返回当前是非环路的
}
int main() {
int n = 4;
g = vector<vector<int>>(n, vector<int>());
g[0].push_back(1);
g[1].push_back(0);
g[1].push_back(2);
g[2].push_back(1);
g[2].push_back(3);
g[3].push_back(2);
bool res = dfs(0,-1,g);
cout<<res;
g[0].push_back(3);
g[3].push_back(0);
res = dfs(0,-1,g);
cout<<res;
return 0;
}
整体代码(会超时)
#include <iostream>
#include <queue>
#include <vector>
#include<memory>
using namespace std;
bool dfs(int cur, int pre ,vector<vector<int>> g,vector<int> visit){
if( visit[cur]){
return true;
}// 有环路
visit[cur]= true;
for( int next: g[cur]){
if(next != pre){
bool subcondition = dfs(next,cur,g, visit);
if (subcondition){ return true;}
}
}
return false; // 如果遍历了所有后续节点,没有返回true,返回当前是非环路的
}
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>> edges) {
if ( edges.size() == 0)
return {0,0};
int n = edges.size();
vector<vector<int>> G(n+1); //二维数组中的整数在1到N之间,其中N是输入数组的大小。
for (int i = 0; i < edges.size(); i++) {
int from = edges[i][0];
int to = edges[i][1];
G[from].push_back(to);
G[to].push_back(from);
vector<int> visit(n+1);
if(dfs(from, -1, G, visit))// 从当前节点出发查找
return edges[i];
}
return {0,0};
}
};
int main()
{
unique_ptr<Solution> mysolo = unique_ptr<Solution>(new Solution());
cout<<"Hello World"<<endl;
vector< vector<int> >edge = {{1,2},{1,3},{2,3}};
vector<int> res = mysolo->findRedundantConnection(edge);
for(auto v: res){
cout<<v<<"-->";
}
return 0;
}