实用指南:代码随想录day56图论6
108. 冗余的边
#include<bits/stdc++.h>
using namespace std;
bool flag=false;
vector<pair<
int,int>> ans;
vector<
int>
father(1001,0);
void init()
{
for(int i=1;i<=1001;i++)
{
father[i]=i;
}
}
int find(int u)
{
if(u==father[u]) return u;
else return father[u]=find(father[u]);
}
void join(int u,int v)
{
int x=find(u);
int y=find(v);
if(x==y) //成环
{
ans.push_back({u,v
});
return ;
}
father[y]=x;
}
int main() {
int n;
cin >> n ;
init();
for(int i=0;i<n;i++)
{
int u,v;
cin>>u>>v;
join(u,v);
}
int k=ans.size()-1;
cout<<ans[k].first<<
" "<<ans[k].second;
}
109. 冗余连接II
情况 删除哪条边
有一个节点入度为2,无环 删除后出现的那条(cand2)
有一个节点入度为2,有环 删除先出现的那条(cand1)
无节点入度为2,但出现环 删除成环边
#include <iostream>
#include <vector>
using namespace std;
const int MAXN = 1005;
int parent[MAXN];
// 并查集用
int inDegree[MAXN];
// 入度数组
pair<
int, int> cand1 = {
-1, -1
}, cand2 = {
-1, -1
};
// 两个指向同一节点的边(如果有)
int find(int x) {
if (parent[x] != x)
parent[x] = find(parent[x]);
return parent[x];
}
bool unionSet(int u, int v) {
int fu = find(u);
int fv = find(v);
if (fu == fv) return false;
// 成环
parent[fv] = fu;
return true;
}
int main() {
int n;
cin >> n;
vector<pair<
int, int>>
edges(n);
for (int i = 0; i < n;
++i)
cin >> edges[i].first >> edges[i].second;
vector<
int>
parentNode(n + 1, 0);
// Step 1: 先检查是否有入度为 2 的点
for (auto&
[u, v] : edges) {
if (parentNode[v] == 0) {
parentNode[v] = u;
} else {
// 找到了入度为2的节点 v
cand1 = {parentNode[v], v
};
// 先到来的边
cand2 = {u, v
};
// 后到来的边(本应被删除)
break;
}
}
// Step 2: 初始化并查集
for (int i = 0; i <= n;
++i) parent[i] = i;
// Step 3: 遍历边,跳过 cand2(即后出现导致入度为2的边)
for (auto&
[u, v] : edges) {
if (make_pair(u, v) == cand2) continue;
if (!unionSet(u, v)) {
// 成环,若没有入度为2节点,返回当前边
if (cand1.first == -1) {
cout << u <<
" " << v << endl;
return 0;
} else {
// 有入度为2节点,也成环 -> 返回 cand1(先插入的那条)
cout << cand1.first <<
" " << cand1.second << endl;
return 0;
}
}
}
// 没有成环,说明 cand2 是多余的那条边
cout << cand2.first <<
" " << cand2.second << endl;
return 0;
}