首页 > 其他分享 >代码随想录训练营第60天|冗余连接

代码随想录训练营第60天|冗余连接

时间:2024-10-12 09:48:33浏览次数:3  
标签:int 查集 随想录 find 60 edges vec 节点 冗余

108. 冗余连接

#include <iostream>
#include <vector>
using namespace std;
int n; // 节点数量
vector<int> father(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]);
}
// 判断 u 和 v是否找到同一个根
bool isSame(int u, int v) {
    u = find(u);
    v = find(v);
    return u == v;
}
// 将v->u 这条边加入并查集
void join(int u, int v) {
    u = find(u); // 寻找u的根
    v = find(v); // 寻找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

#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) {
    return u == father[u] ? u : father[u] = find(father[u]);
}
// 将v->u 这条边加入并查集
void join(int u, int v) {
    u = find(u);
    v = find(v);
    if (u == v) return ;
    father[v] = u;
}
// 判断 u 和 v是否找到同一个根
bool same(int u, int v) {
    u = find(u);
    v = find(v);
    return u == v;
}

// 在有向图里找到删除的那条边,使其变成树
void getRemoveEdge(const vector<vector<int>>& edges) {
    init(); // 初始化并查集
    for (int i = 0; i < n; i++) { // 遍历所有的边
        if (same(edges[i][0], edges[i][1])) { // 构成有向环了,就是要删除的边
            cout << edges[i][0] << " " << edges[i][1];
            return;
        } else {
            join(edges[i][0], edges[i][1]);
        }
    }
}

// 删一条边之后判断是不是树
bool isTreeAfterRemoveEdge(const vector<vector<int>>& edges, int deleteEdge) {
    init(); // 初始化并查集
    for (int i = 0; i < n; i++) {
        if (i == deleteEdge) continue;
        if (same(edges[i][0], edges[i][1])) { // 构成有向环了,一定不是树
            return false;
        }
        join(edges[i][0], edges[i][1]);
    }
    return true;
}

int main() {
    int s, t;
    vector<vector<int>> edges;
    cin >> n;
    vector<int> inDegree(n + 1, 0); // 记录节点入度
    for (int i = 0; i < n; i++) {
        cin >> s >> t;
        inDegree[t]++;
        edges.push_back({s, t});
    }

    vector<int> vec; // 记录入度为2的边(如果有的话就两条边)
    // 找入度为2的节点所对应的边,注意要倒序,因为优先删除最后出现的一条边
    for (int i = n - 1; i >= 0; i--) {
        if (inDegree[edges[i][1]] == 2) {
            vec.push_back(i);
        }
    }
    // 情况一、情况二
    if (vec.size() > 0) {
        // 放在vec里的边已经按照倒叙放的,所以这里就优先删vec[0]这条边
        if (isTreeAfterRemoveEdge(edges, vec[0])) {
            cout << edges[vec[0]][0] << " " << edges[vec[0]][1];
        } else {
            cout << edges[vec[1]][0] << " " << edges[vec[1]][1];
        }
        return 0;
    }

    // 处理情况三
    // 明确没有入度为2的情况,那么一定有有向环,找到构成环的边返回就可以了
    getRemoveEdge(edges);
}

有向树性质:只有根节点入度为0,其他节点入度都为1(因为该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点),所以:

  • 如果找到入度为2的点,那么删一条指向该节点的边

         isTreeAfterRemoveEdge() 判断删一个边之后是不是有向树

  • 如果没有入度为2的点,分析图中是否有环,删掉构成环的边

   getRemoveEdge() 确定图中一定有了有向环,那么要找到需要删除的那条边

标签:int,查集,随想录,find,60,edges,vec,节点,冗余
From: https://blog.csdn.net/jiyisuifeng1991/article/details/142869850

相关文章

  • 【gpt搬运】bash脚本压缩png,jpg图片,当图片大小大于60kb或者尺寸大于500px*500px的时
    在这个任务中,Bash脚本需要检查图片的文件大小和尺寸(宽度和高度),然后决定是否压缩图片。我们可以继续使用jpegoptim和pngquant来压缩.jpg和.png图片。为了检查图片的尺寸,使用imagemagick的identify命令来获取宽度和高度。准备工具:安装imagemagick:用于检查图片的宽......
  • 104th 2024/10/8 模拟赛总结60
    T1有感觉,因为AB组一起打,所以下意识认为是水题(实际上也不算难?)就直接开始想从深向浅直接扫一遍,能转就转显然错,从浅向深扫一遍同样不对,因为不知道往上转移的顺序比如,设该点为x,是0,有的儿子可能转移到x,其子树内转移的次数比另一个儿子多,所以就要优先它不好处理,看到数据,给了一档2e5,一......
  • Python下5分钟k线数据转15、30、60分钟线数据的探索
     在做股票相关的项目,需要把通达信的5分钟k线数据转为15、30、60分钟线来做后续处理,参考了一些资料,发现pandas的resample可以实现。#通过5分钟线生成15、30、60分钟线defchangeLc5Cycle(stockid,cycle):cycle_list=['15min','30min','60min']ifcyclenotin......
  • 代码随想录算法训练营day12|144.二叉树的前序遍历 94.二叉树的中序遍历 145.二叉
    学习资料:https://programmercarl.com/二叉树理论基础.html二叉树:满二叉树、完全二叉树、二叉搜索数、平衡二叉搜索树;链式存储、顺序存储;前序/中序/后序遍历递归法、迭代法,层序深度优先搜索dfs,广度优先搜索学习记录:144.二叉树的前序遍历(也要注重二叉数的输入方式;递归法比迭......
  • 代码随想录Day23 | LeetCode 455. 分发饼干、LeetCode 53. 最大子数组和、LeetCode 37
    LeetCode455.分发饼干贪心就是干classSolution:deffindContentChildren(self,g:List[int],s:List[int])->int:g.sort(reverse=True)s.sort(reverse=True)i=j=0res=0whilei<len(g)andj<len(......
  • 代码随想录算法训练营 | 完全背包,518. 零钱兑换 II,377. 组合总和 Ⅳ,70. 爬楼梯 (进阶)
    完全背包题目链接:完全背包文档讲解︰代码随想录(programmercarl.com)视频讲解︰完全背包日期:2024-10-11想法:dp数组设置思路跟01背包一样,不同在遍历上,完全背包遍历背包大小是从weight[i]开始的(背包空间小于weight[i]就没有意义,不用考虑,直接用之前的对应数值就行了),从前往后遍历就能......
  • ETA6005Q3Q 2.5A带动态路径管理的单节锂电开关型充电器
    2.5A带动态路径管理的单节锂电开关型充电器  ETA6005是一款充电电流达2.5A的单节锂电开关型充电。其集成了动态路径管理功能,内部路径的开关内阻仅50mohm,允许系统在没有电池的情况下,仍然可以在适配器存在是维持系统正常工作。ETA6005有特有的2级充电设定可通过引脚的0,1来设......
  • 基于django的民宿预定管理系统的设计与实现---附源码60197
    目录摘要1绪论1.1选题背景与意义1.2国内外研究现状1.3论文结构与章节安排2系统分析2.1可行性分析2.1.1经济可行性分析2.1.2技术可行性分析2.1.3操作可行性分析2.2系统流程分析2.2.1系统开发流程2.2.2用户登录流程2.2.3系统操作流程2.2.......
  • 01数组算法/代码随想录
    一、数组好久没写算法题,之前喜欢按着习惯选择刷题,很早以前就听说代码随想录,今天跟着代码随想录再过一遍算法1.1二分查找常见疑问middle一定是在[left,right]这个范围内标准代码不会越界,因为在elseif中出现越界后,下一次循环就不会通过左闭右闭区间代码示例public......
  • 代码随想录算法训练营 | 1049. 最后一块石头的重量 II,494. 目标和,474.一和零
    1049.最后一块石头的重量II题目链接:1049.最后一块石头的重量II文档讲解︰代码随想录(programmercarl.com)视频讲解︰最后一块石头的重量II日期:2024-10-10想法:这这么会是分割等和子集一类的问题。。。Java代码如下:classSolution{publicintlastStoneWeightII(int[]......