Cod sursa(job #2657058)

Utilizator nicu_ducalNicu Ducal nicu_ducal Data 9 octombrie 2020 16:58:47
Problema Arbore partial de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.2 kb
#include <bits/stdc++.h>
using namespace std;

#define debug(x) cerr << #x << " = " << x << "\n"
#define all(x) (x).begin(),(x).end()
#define len(x) (x).length()
#define sqr(x) (x) * (x)

using ull = unsigned long long;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

template <typename T>
ostream& operator<<(ostream &os, const vector<T> &v) { os << '{'; string sep; for (const auto &x : v) os << sep << x, sep = ", "; return os << '}'; }
template <typename A, typename B>
ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }

const int INF = INT_MAX;
const int MOD = 1e9 + 7;
const double EPS = 1e-9;
const double PI = acos(-1);

ll t, n;

// Algorithm: Prim's Algorithm - Minimum Spanning Tree
// Author: Neeecu
// Complexity: O(|E| * log|N|);

struct Edge {
    int from, to, w;

    Edge(int _from, int _to, int _w) : from(_from), to(_to), w(_w) {}

    bool operator<(const Edge& other) const {
        return w < other.w;
    }
};

struct min_span_tree {
    vector<vector<Edge>> adj;
    vector<Edge> mst;
    vector<bool> in_tree;
    vector<Edge> min_edge;
    ll total_w = 0;

    min_span_tree(int n) {
        adj.resize(n + 1);
        in_tree.resize(n + 1, false);
        min_edge.push_back(Edge(-1, -1, -1));
    }

    void add_edge(int to, int from, int weight) {
        adj[to].push_back(Edge(to, from, weight));
        adj[from].push_back(Edge(from, to, weight));
    }

    void create_mst() {
        in_tree[1] = true;
        min_edge.push_back(Edge(-1, 1, 0));
        set<pair<int, pair<int, int>>> s;
        s.insert({0, {-1, 1}});
        for (int i = 2; i <= n; i++){
            min_edge.push_back(Edge(-1, i, INF));
            s.insert({INF, {-1, i}});
        }

        while (not s.empty()) {
            auto t = *s.begin();
            Edge cur_edge = Edge(t.second.first, t.second.second, t.first);
            s.erase(s.begin());

            /// Add current edge to MST
            if (cur_edge.to != 1) {
                total_w += cur_edge.w;
                mst.push_back(Edge(cur_edge.from, cur_edge.to, cur_edge.w));
                in_tree[cur_edge.to] = true;
            }

            /// Update edges
            for (auto edg: adj[cur_edge.to]) {
                if (not in_tree[edg.to] and edg.w < min_edge[edg.to].w) {
                    s.erase({min_edge[edg.to].w, {min_edge[edg.to].from, min_edge[edg.to].to}});
                    min_edge[edg.to] = edg;
                    s.insert({min_edge[edg.to].w, {min_edge[edg.to].from, min_edge[edg.to].to}});
                }
            }
        }
    }
};

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    ifstream cin("apm.in");
    ofstream cout("apm.out");

    ll m, from, to, w;
    cin >> n >> m;
    min_span_tree MST(n);
    for (int i = 1; i <= m; i++) {
        cin >> from >> to >> w;
        MST.add_edge(from, to, w);
    }

    MST.create_mst();

    cout << MST.total_w << "\n" << n - 1 << "\n";
    for (auto edg: MST.mst) cout << edg.from << " " << edg.to << "\n";

    return 0;
}