Skip to content

T27351:01最小生成树

mst, http://cs101.openjudge.cn/practice/27351/

思路:优先选权值为 0 的边,再用权值为 1 的边补全连通性

cpp
#include <iostream>
#include <vector>
#include <unordered_set>
#include <queue>
using namespace std;

const int MAX_N = 200005;
unordered_set<int> adj[MAX_N];  
unordered_set<int> unvisited; 
queue<int> q;             

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        unvisited.insert(i);
    }
    for (int i = 0; i < m; ++i) {
        int a, b;
        cin >> a >> b;
        adj[a].insert(b);
        adj[b].insert(a);
    }
    int component_count = 0;
    for (int i = 1; i <= n; ++i) {
        if (unvisited.count(i)) { 
            component_count++;
            q.push(i);
            unvisited.erase(i); 
            while (!q.empty()) {
                int u = q.front();
                q.pop();
                vector<int> neighbors;
                for (auto it = unvisited.begin(); it != unvisited.end();) {
                    int v = *it;
                    if (adj[u].count(v) == 0) {
                        neighbors.push_back(v);
                        it = unvisited.erase(it);  
                    } else {
                        it++;
                    }
                }
                for (int v : neighbors) {
                    q.push(v);
                }
            }
        }
    }
    cout << component_count - 1 << endl;

    return 0;
}