笔记:代码随想录算法训练营day62:108.冗余连接、109.冗余连接II

学习资料:代码随想录

108. 冗余连接

卡码网题目链接(ACM模式)

判断是否有环的依据为,利用并查集,isSame函数,判断当下这条边的两个节点入集前是否为同根,如果是的话,该边就是会构成环的那条边

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;
 
int n;
vector<int> father=vector<int>(1001,0);
 
void init(){
    for(int i=0;i<n;i++){
        father[i]=i;
    }
}
int find(int u){
    return u==father[u]?u:father[u]=find(father[u]);
}
 
bool isSame(int u,int v){
    u=find(u);
    v=find(v);
    return u==v;
}
 
void join(int u,int v){
    u=find(u);
    v=find(v);
    if(u==v) return;
    father[v]=u;
}
 
int main(){
    int s,t;
    cin>>n;
    init();
    for(int i=0;i<n;i++){
        cin>>s>>t;
        if(isSame(s,t)) {
            cout<<s<<' '<<t<<endl;
            return 0;
        }
        else{
            join(s,t);
        }
    }
}

109. 冗余连接II

卡码网题目链接(ACM模式)

分三种情况:代码随想录

对于有两个入度的节点的情况,需要先倒序记录节点入度情况,找到入度为2的那个节点对应的两条边,判断应该删除哪条边。判断方法为,先看第一条(之前是倒序遍历,即看最后这条),用isSame函数判段是否为构成环的这条边,如果是,cout这条,如果不是cout另一条;

如果没有入度为2的节点,即情况3,直接用isSame函数判断就可以了

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;
int n;
vector<int> father=vector<int>(1001,0);
void init(){
    for(int i=1;i<=n;i++){
        father[i]=i;
    }
}
 
int find(int u){
   return u==father[u]?u:father[u]=find(father[u]);
}
 
bool isSame(int u,int v){
    u=find(u);
    v=find(v);
    return u==v;
}
 
void join(int u,int v){
    u=find(u);
    v=find(v);
    if(u==v) return;
    father[v]=u;
}
 
bool isTreeAfterDeleteEdge(const vector<vector<int>>& edges,int todelete){
    init();
    for(int i=0;i<n;i++){
        if(i==todelete){
            continue;
        }
        if(isSame(edges[i][0],edges[i][1])) return false;
        join(edges[i][0],edges[i][1]);
    }
    return true;
}
 
void deletedEdge(const vector<vector<int>>& edges){
    init();
    for(int i=0;i<n;i++){
        if(isSame(edges[i][0],edges[i][1])){
            cout<<edges[i][0]<<' '<<edges[i][1];
            return;
        }
        join(edges[i][0],edges[i][1]);
    }
}
 
 
int main(){
    cin>>n;
    vector<vector<int>> edges;
    vector<int> inDegree(n+1,0);
    int s,t;
    for(int i=0;i<n;i++){
        cin>>s>>t;
        edges.push_back({s,t});
        inDegree[t]++;
    }
    vector<int> doubleDegree;
    for(int i=n-1;i>=0;i--){
        if(inDegree[edges[i][1]]==2){
            doubleDegree.push_back(i);
        }
         
    }
    if(doubleDegree.size()>0){
        if(isTreeAfterDeleteEdge(edges,doubleDegree[0])){
            cout<<edges[doubleDegree[0]][0]<<' '<<edges[doubleDegree[0]][1];
        }
        else{
            cout<<edges[doubleDegree[1]][0]<<' '<<edges[doubleDegree[1]][1];
        }
        return 0;
    }
 
    deletedEdge(edges);
 
}

有几个小点:

1、 既然 isTreeAfterRemoveEdge()getRemoveEdge() 都是靠并查集判断是否成环,能不能只用 getRemoveEdge() 一个函数来处理所有情况?

不能!

getRemoveEdge() 只能处理「无入度为 2」的情况(即情况三)

如果你碰到的是「有一个点入度为 2」(即情况一、情况二),就必须要先判断删哪一条边,这一步 getRemoveEdge() 做不到。

**2、**对于find函数会改变并查集的结构,这并不改变每一个节点的根节点,所以虽然在join函数和isSame函数的使用中,find会使并查集结构改变,对判断没有影响

3、 对于vector,赋值方法vi = x需要以前设置vector大小, 赋值方法v.push_back(x)不需要提前设置vector大小

相关推荐
星恒随风4 小时前
C++ STL 栈详解:stack 的使用、经典题目与简单模拟实现
开发语言·数据结构·c++·笔记·学习
玖玥拾6 小时前
Unity 3D 笔记(十一)UI 框架进阶:栈弹窗交互、BasePanel 基类虚方法、DoTween 界面动画
笔记·3d·unity
FellAveal6 小时前
【Go语言入门学习笔记】Part13.结构体与接口
笔记·学习·golang
学计算机的计算基6 小时前
回溯算法下篇:四道经典题讲透约束剪枝、原地标记、预计算与状态压缩
java·笔记·算法
雷工笔记6 小时前
Ubuntu迁移记录
笔记·ubuntu
一只小菜鸡..6 小时前
Stanford CS144 学习笔记 (九):大师访谈与互联网的未来
笔记·学习
十月的皮皮6 小时前
STM32从零到量产开发:四路继电器工业控制模块开发实战笔记(小白视角)
c语言·笔记·stm32·stm32cubemx·hal库
疯狂打码的少年6 小时前
【软件工程】软件项目管理(人员/产品/过程/项目)
笔记·软件工程
zyplayer-doc7 小时前
研发接口文档怎么长期维护:zyplayer-doc把API、Markdown和变更记录放进同一个知识库
大数据·数据库·人工智能·笔记·pdf·ocr
2CM_Embed7 小时前
F28379D 下载后 VOFA+ 无数据、Reset 后恢复:一次 TZ 中断误触发排查记录
笔记·单片机·sci·c2000·f28379d·vofa·tz