代码随想录算法训练营第六十天|多余的边?从基础到进阶!

108. 多余的边

思路:这题是无向图,所以实际上是一棵树。现在在这棵树上的基础上,添加一条边(依然是n个节点,但有n条边),就会使这个图变成了有环图。如果边的两个节点已经出现在同一个集合里,说明着边的两个节点已经连在一起了,再加入这条边一定就出现环了。那么这个操作用之前的并查集模板就可以解决。

我的代码:

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;
int n;
vector<int> father(1001,0);
void init() {
    for(int i=1;i<=n;i++) father[i]=i;
}

int find(int u) {
    if(father[u]==u) return u;
    else return father[u]=find(father[u]);
}
bool issame(int u,int v) {
    u=find(u);
    v=find(v);
    if(u==v) return true;
    else return false;
}
void join(int u,int v) {
    u=find(u);
    v=find(v);
    if(u==v) return;
    else 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;
            return 0;
        }
        else join(s,t);
    }
    return 0;
}

109. 多余的边II

思路:这道题从无向图变成了有向图,说实话我是没想出来有三种情况.......这道题需要用到入度这个概念,入度就是一个树节点被父节点个节点指向的个数。情况一:如果我们找到入度为2的点,那么删一条指向该节点的边就行了。情况二,只能删特定的一条边,因为删除另一条边的时候就会构不成有向图。情况三: 如果没有入度为2的点,说明图中有环了,这个时候可以用上一题的逻辑找到成环的最后一条边。

istree():判断删一个边之后是不是有向树: 将所有边的两端节点分别加入并查集,遇到要 要删除的边则跳过,如果遇到即将加入并查集的边的两端节点 本来就在并查集了,说明构成了环。如果顺利将所有边的两端节点(除了要删除的边)加入了并查集,则说明 删除该条边 还是一个有向树

getremove:确定图中一定有了有向环,那么要找到需要删除的那条边: 将所有边的两端节点分别加入并查集,如果遇到即将加入并查集的边的两端节点 本来就在并查集了,说明构成了环。

我的代码:

cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;
int n;
vector<int> father(1001,0);
void init() {
    for(int i=1;i<=n;i++) father[i]=i;
}

int find(int u) {
    if(father[u]==u) return u;
    else return father[u]=find(father[u]);
}
bool issame(int u,int v) {
    u=find(u);
    v=find(v);
    if(u==v) return true;
    else return false;
}
void join(int u,int v) {
    u=find(u);
    v=find(v);
    if(u==v) return;
    else father[v]=u;
}
void getremove(const vector<vector<int>> edge) {
    init();
    for(int i=0;i<n;i++) {
        if(issame(edge[i][0],edge[i][1])) {
            cout<<edge[i][0]<<" "<<edge[i][1];
        }
        else join(edge[i][0],edge[i][1]);
    }
}
bool istree(const vector<vector<int>> edge,int deletenode) {
    init();
    for(int i=0;i<n;i++) {
        if(i==deletenode) continue;
        if(issame(edge[i][0],edge[i][1])) {
            return false;
        }
        else {
            join(edge[i][0],edge[i][1]);
        }
    }
    return true;
}
int main() {
    cin>>n;
    int s,t;
    vector<vector<int>> edge;
    vector<int> indgree(n+1,0);
    for(int i=0;i<n;i++) {
        cin>>s>>t;
        indgree[t]++;
        edge.push_back({s,t});
    }
    vector<int> vec;
    for(int i=n-1;i>=0;i--) {
        if(indgree[edge[i][1]]==2) {
            vec.push_back(i);
        }
    }
    if(vec.size()>0) {
        if(istree(edge,vec[0])) {
            cout<<edge[vec[0]][0]<<" "<<edge[vec[0]][1]<<endl;
        }
        else cout << edge[vec[1]][0] << " " << edge[vec[1]][1];
        return 0;
    }
    getremove(edge);
}

今日总结

今天的109还是很有难度,思路上就不好想,代码实现上也有一些小坑。最近学算法的时间经常被压缩,或者到了学的时间已经超长待机一天了,接下来要好好休息一下,再回来总结一下。冲!

相关推荐
程与留5 小时前
15_国际化和本地化:tr()、ts 文件、QM 文件、多语言切换
c++·qt
地平线开发者6 小时前
【模型轻量化专题】衡量模型轻量性的指标
算法
程与留7 小时前
14_Qt 样式表(QSS)入门(语法、选择器、美化实战)
c++·qt
学习星球9 小时前
OFDM技术精讲:正交性推导、循环前缀原理与80行Python链路仿真(附实测数据)
算法·面试·前端框架
欧特克_Glodon15 小时前
OpenCV计算机视觉开发入门与实践<二十七>:图像分割概述
c++·人工智能·opencv·计算机视觉
蒸蒸yyyyzwd15 小时前
cpp 选手秋招学习笔记 day21
c++·面试·八股
alphaTao15 小时前
LeetCode 每日一题 2026/8/24-2026/8/30
python·算法·leetcode
Interview Aid11215 小时前
TikTok OA 四题分享|半小时内 AC,题目基本都是实现题
java·开发语言·算法·面试·职场和发展
CoderIsArt1 天前
C#中UI 线程与 Dispatcher
开发语言·ui·c#
顶点多余1 天前
那些在算法中适合巩固的知识点---1
java·前端·算法