news 2026/9/12 3:53:03

代码随想录算法训练营Day48 | 108.冗余连接、109.冗余连接II

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
代码随想录算法训练营Day48 | 108.冗余连接、109.冗余连接II

KamaCoder108.冗余连接

108. 多余的边

1.思路

对于边(s, t),使用find(s)find(t)分别查找st所在集合的根节点。

如果根节点相同:说明st本来就在同一个集合中,即它们已经连通。此时,边(s, t)的加入必定会形成环。这就是我们要找的第一条成环边,直接输出(s, t)并结束程序。

如果根节点不同:说明st尚未连通。此时,使用join(s, t)将它们所在的两个集合合并,表示它们现在连通了。然后继续处理下一条边。

#include <iostream> #include <vector> using namespace std; int n; vector<int>father(1005,1); void init(){ for(int i=1;i<=n;i++){ father[i]=i; } } int find(int u){ if(u==father[u]){ return u; } return father[u]=find(father[u]); } // 将v->u 这条边加入并查集 int join(int u,int v){ u=find(u); v=find(v); if(u==v) return 0; // 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回 father[u]=v; return 1; } int main(){ cin>>n; init(); for(int i=0;i<n;i++){ int s,t;cin>>s>>t; if(!join(s,t)){ cout<<s<<" "<<t<<endl; break; } } return 0; }

2.思考

这道题只需要在合并的时候判断两个节点的父节点是否相同即可,相同则说明两节点已经在同一集合了,直接输出当前两节点。

3.Reference:108. 多余的边


KamaCoder109.多余的边II

109. 多余的边II

1.思路

这个图最初是一棵有n个节点的树(有n-1条边),然后被额外添加了一条有向边。由于添加了这条边,图可能不再是一棵树。这会导致两种可能的问题:

存在环:新添加的边连接了已经连通的两个节点;存在入度为2的节点:新添加的边指向了一个已经有入边的节点。

目标:找出这条被添加的“冗余”边,移除它后,图能重新变为一棵树。

情况一:存在入度为 2 的节点 (vec.size() > 0)

冗余边必定是edge1edge2中的一条,我们需要判断到底是哪一条。

首先尝试删除vec[1]对应的边,如果isdelete返回true,说明删除edge2后图是合法的, 那么edge2就是答案。如果isdelete返回false,说明删除edge2后图仍然有环。这意味 着edge1才是构成环的边,因此edge1是答案。

情况二:不存在入度为 2 的节点 (vec.size() == 0)

既然没有入度为 2 的节点,那么问题必定是存在一个环。而且,这个环就是由那条多 余的边造成的。

直接使用并查集遍历所有n条边,找到第一个构成环的边即可。

如果issame(u, v)true,说明uv已经连通,当前边(u, v)就是导致环的冗余边。直 接输出并结束程序。

如果issame(u, v)false,则执行join(u, v),继续检查下一条边。

#include <iostream> #include <vector> using namespace std; int n; vector<int>father(1005,1); void init(){ for(int i=1;i<=n;i++){ father[i]=i; } } int find(int u){ if(u==father[u]){ return u; } return 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[u]=v; } // 删一条边之后判断是不是树 bool isdelete(vector<pair<int,int>>&edges,int u){ init(); for(int i=1;i<=n;i++){ if(i==u) continue; if(issame(edges[i].first,edges[i].second)){ // 构成有向环了,一定不是树 return false; } else join(edges[i].first,edges[i].second); } return true; } int main(){ cin>>n; vector<pair<int,int>>edges(n+1); // 存边 vector<int>indegree(n+1,0); // 记录节点入度 for(int i=1;i<=n;i++){ int s,t;cin>>s>>t; edges[i]={s,t}; indegree[t]++; } vector<int>vec; // 找入度为2的节点所对应的边 for(int i=1;i<=n;i++){ if(indegree[edges[i].second]==2){ vec.push_back(i); } } if(vec.size()>0){ // 优先删vec[1] 对应这条边 if(isdelete(edges,vec[1])){ cout<<edges[vec[1]].first<<" "<<edges[vec[1]].second<<endl; } else cout<<edges[vec[0]].first<<" "<<edges[vec[0]].second<<endl; return 0; } // 明确没有入度为2的情况,那么一定有有向环,找到构成环的边返回就可以了 // 在有向图里找到删除的那条边,使其变成树 init(); for(int i=1;i<=n;i++){ if(issame(edges[i].first,edges[i].second)){ cout<<edges[i].first<<" "<<edges[i].second<<endl; return 0; } else join(edges[i].first,edges[i].second); } return 0; }

2.思考

这道题较上道题难度天差地别。有多余的边,我们就要讨论几种情况,第一种就是有入度为 2 的节点,那么显而易见,该节点相关的两条边中的一条就是冗余的边,那么此时我们就假设删除第二条边,然后看剩余边能否构成有向树,如果能,那么该条边就是冗余的,否则,第一条边就是冗余的;还有一种情况就不存在入度为 2 的节点,但此时还是存在冗余边,所以就是形成了环,此时也就来到了 多余的边 那道题的情况,只需要依次连接节点,遇到在同一集合的两节点,立即输出返回,此时两节点构成的边即为多余的边。

3.Reference:109. 冗余连接II | 代码随想录

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 18:27:12

Day 16 C++提高之模板

Day 16 C提高之模板 一、模板的概念 模板就是建立通用的模具&#xff0c;大大提高复用性。例如&#xff0c;生活中的模板&#xff1a;一寸照片的模板、PPT模板、论文模板。 模板特点&#xff1a;通用性很强&#xff0c;但是不能直接使用&#xff0c;只是一个框架&#xff0c;模…

作者头像 李华
网站建设 2026/9/12 19:27:31

蓝桥杯 162.通电(Prim算法)

2015 年&#xff0c;全中国实现了户户通电。作为一名电力建设者&#xff0c;小明正在帮助一带一路上的国家通电。这一次&#xff0c;小明要帮助 nn 个村庄通电&#xff0c;其中 1 号村庄正好可以建立一个发电站&#xff0c;所发的电足够所有村庄使用。现在&#xff0c;这 nn 个…

作者头像 李华
网站建设 2026/9/12 1:22:45

ContextMenuManager仿写文章Prompt

ContextMenuManager仿写文章Prompt 【免费下载链接】ContextMenuManager &#x1f5b1;️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 核心要求 请基于ContextMenuManager项目&#xff0c;创作一篇结构新颖、语气…

作者头像 李华
网站建设 2026/9/11 8:33:22

AI原生应用中的增量学习:多任务学习

AI原生应用中的增量学习&#xff1a;多任务学习——让AI像人一样“持续成长” 一、引入&#xff1a;从Copilot的“进化”说起 清晨的咖啡馆里&#xff0c;程序员小陆正对着电脑发愁&#xff1a;他刚接手一个跨语言项目&#xff0c;需要用Python写后端逻辑&#xff0c;用Go做微服…

作者头像 李华
网站建设 2026/9/12 13:50:44

解锁Slick轮播隐藏技能:5分钟打造专属分页指示器设计

解锁Slick轮播隐藏技能&#xff1a;5分钟打造专属分页指示器设计 【免费下载链接】slick the last carousel youll ever need 项目地址: https://gitcode.com/GitHub_Trending/sl/slick 想要让你的slick轮播组件在众多网站中脱颖而出&#xff1f;分页指示器&#xff08;…

作者头像 李华
网站建设 2026/9/12 2:28:34

Ubuntu命令行部署GPT-SoVITS语音合成

Ubuntu命令行部署GPT-SoVITS语音合成 在远程服务器上做AI语音项目&#xff0c;最头疼的莫过于没有图形界面——WebUI打不开、操作全靠SSH终端。最近尝试在纯命令行环境下部署 GPT-SoVITS&#xff0c;这个目前非常火的少样本语音克隆系统&#xff0c;发现虽然官方提供了Web界面…

作者头像 李华