实用指南:代码随想录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;
    }
posted @ 2025-08-16 16:46  yfceshi  阅读(7)  评论(0)    收藏  举报