图论05&06

并查集

int n = 1005; // n根据题目中节点数量而定,一般比节点数量大一点就好
vector<int> father = vector<int> (n, 0); // C++里的一种数组结构
vector<int> rank = vector<int> (n, 1); // 初始每棵树的高度都为1

// 并查集初始化
void init() {
    for (int i = 0; i < n; ++i) {
        father[i] = i;
        rank[i] = 1; // 也可以不写
    }
}
// 并查集里寻根的过程
int find(int u) {
    return u == father[u] ? 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 (rank[u] <= rank[v]) father[u] = v; // rank小的树合入到rank大的树
    else father[v] = u;

    if (rank[u] == rank[v] && u != v) rank[v]++; // 如果两棵树高度相同,则v的高度+1,因为上面 if (rank[u] <= rank[v]) father[u] = v; 注意是 <=
}

107. 寻找存在的路径

#include <iostream>
#include <vector>
using namespace std;

int n; // 节点数量
vector<int> father = vector<int> (101, 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]);
}

// 判断 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 m, s, t, source, destination;
    cin >> n >> m;
    init();
    while (m--) {
        cin >> s >> t;
        join(s, t);
    }
    cin >> source >> destination;
    if (isSame(source, destination)) cout << 1 << endl;
    else cout << 0 << endl;
}

108. 冗余的边

#include <iostream>
#include <vector>

using namespace std;

int n;
vector<int> father(1001, 0);

void init() {
    for (int i = 0; i < father.size(); i++) {
        father[i] = i;
    }
}

int find(int a) {
    if (a == father[a]) return a;
    return find(father[a]);
}

void join(int a, int b) {
    a = find(a);
    b = find(b);
    if (a == b) return;
    father[a] = b;
}

bool isSame(int a, int b) {
    a = find(a);
    b = find(b);
    if (a == b) return true;
    return false;
}

int main() {
    cin >> n;
    int s, t;
    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

#include <iostream>
#include <vector>

using namespace std;

int n;
vector<int> father(1001, 0);

void init() {
    for (int i = 0; i < father.size(); i++) {
        father[i] = i;
    }
}

int find(int a) {
    if (a == father[a]) return father[a];
    return find(father[a]);
}

void join(int a, int b) {
    a = find(a);
    b = find(b);
    if (a == b) return;
    father[a] = b;
}

bool isSame(int a, int b) {
    a = find(a);
    b = find(b);
    if (a == b) return true;
    return false;
}

bool isTree(vector<pair<int, int>> edge, pair<int, int> e) {
    init();
    for (int i = 0; i < edge.size(); i++) {
        if (edge[i] == e) continue;
        if (isSame(edge[i].first, edge[i].second)) {
            return false;
        }
        else {
            join(edge[i].first, edge[i].second);
        }
    }
    return true;
}


int main() {
    cin >> n;
    int s, t;
    vector<pair<int, int>> edge;
    vector<int> inorder(n + 7, 0);
    for (int i = 0; i < n; i++) {
        cin >> s >> t;
        edge.push_back({s, t});
        inorder[t]++;
    }
    vector<int> vec;
    for (int i = n - 1; i >= 0; i--) {
        if (inorder[edge[i].second] == 2){
             vec.push_back(i);
        }
        
    }
    if (vec.size() > 0) {
        if (isTree(edge, edge[vec[0]])) {
            cout << edge[vec[0]].first << " " << edge[vec[0]].second;
            return 0;
        }
        else {
            cout << edge[vec[1]].first << " " << edge[vec[1]].second;
            return 0;
        }     
    }
    init();
    for (int i = 0; i < n; i++) {
        if (isSame(edge[i].first, edge[i].second)) {
            cout << edge[i].first << " " << edge[i].second;
            return 0;
        }
        else {
            join(edge[i].first, edge[i].second);
        }
    }

    return 0;
    
}
posted @ 2025-08-18 11:15  skyler886  阅读(9)  评论(0)    收藏  举报