• [一本通学习笔记] 最小生成树


    10065. 「一本通 3.1 例 2」北极通讯网络

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 500005;
    int fa[N], n, k, ind;
    double x[N], y[N];
    void init() {
        for (int i = 0; i <= n; i++) fa[i] = i;
    }
    int find(int p) { return (p == fa[p]) ? (p) : (fa[p] = find(fa[p])); }
    void merge(int p, int q) {
        p = find(p);
        q = find(q);
        fa[p] = q;
    }
    double dist(double x1, double y1, double x2, double y2) {
        return sqrt(pow((x2 - x1), 2) + pow((y2 - y1), 2));
    }
    struct Edge {
        int u, v;
        double w;
        bool operator<(const Edge &b) { return w < b.w; }
    } e[N];
    double ans = 0;
    int cnt = 0;
    
    int main() {
        // ios::sync_with_stdio(false);
        cin >> n >> k;
        for (int i = 1; i <= n; i++) {
            cin >> x[i] >> y[i];
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j < i; j++) {
                Edge tmp;
                tmp.u = i;
                tmp.v = j;
                tmp.w = dist(x[i], y[i], x[j], y[j]);
                e[++ind] = tmp;
            }
        }
        sort(e + 1, e + ind + 1);
        init();
        for (int i = 1; i <= ind; i++)
            if (find(e[i].u) != find(e[i].v)) {
                merge(e[i].u, e[i].v);
                ++cnt;
                if (cnt + k <= n)
                    ans = max(ans, e[i].w);
            }
        cout << setiosflags(ios::fixed) << setprecision(2) << ans << endl;
    }
    

    10066. 「一本通 3.1 练习 1」新的开始

    #include <bits/stdc++.h>
    using namespace std;
    
    int n, p[1005][1005], ans, dis[1005];
    
    int main() {
        ios::sync_with_stdio(false);
        cin >> n;
        dis[n + 1] = 1e+9;
        for (int i = 1; i <= n; i++) cin >> dis[i];
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++) cin >> p[i][j];
        for (int i = 1; i <= n; i++) {
            int mx = n + 1;
            for (int j = 1; j <= n; j++)
                if (dis[j] && dis[mx] > dis[j])
                    mx = j;
            ans += dis[mx];
            for (int j = 1; j <= n; j++) dis[j] = min(dis[j], p[mx][j]);
        }
        cout << ans << endl;
    }
    

    10067. 「一本通 3.1 练习 2」构造完全图

    安全边定理的运用

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll n, m, fa[100005], siz[100005], ans;
    ll find(ll p) { return p == fa[p] ? p : (fa[p] = find(fa[p])); }
    void merge(ll p, ll q) {
        p = find(p);
        q = find(q);
        if (p > q)
            swap(p, q);
        siz[p] += siz[q];
        fa[q] = p;
    }
    struct Edge {
        ll u, v, w;
        bool operator<(const Edge &b) { return w < b.w; }
    } e[100005];
    
    int main() {
        cin >> n;
        for (ll i = 1; i < n; i++) {
            ll u, v, w;
            cin >> u >> v >> w;
            Edge t;
            t.u = u;
            t.v = v;
            t.w = w;
            e[i] = t;
        }
        sort(e + 1, e + n);
        for (ll i = 1; i <= n; i++) fa[i] = i, siz[i] = 1;
        for (ll i = 1; i < n; i++) {
            ans += siz[find(e[i].u)] * siz[find(e[i].v)] * (e[i].w + 1);
            merge(e[i].u, e[i].v);
        }
        cout << ans - n + 1 << endl;
    }
    

    10068. 「一本通 3.1 练习 3」秘密的牛奶运输

    #include <bits/stdc++.h>
    using namespace std;
    #define N 1000005
    #define ll long long
    struct Edge {
        ll u, v, w;
        bool operator<(const Edge &b) { return w < b.w; }
    } e[N];
    ll n, m, ans, fa[N];
    ll find(ll p) { return p == fa[p] ? p : (fa[p] = find(fa[p])); }
    void merge(ll p, ll q) {
        p = find(p);
        q = find(q);
        fa[p] = q;
    }
    vector<pair<ll, ll> > g[N];
    ll h[505][505], vis[505];
    void dfs(ll from, ll p) {
        vis[p] = 1;
        for (ll i = 0; i < g[p].size(); i++) {
            ll q = g[p][i].first;
            if (vis[q])
                continue;
            h[from][q] = max(h[from][p], g[p][i].second);
            dfs(from, q);
        }
    }
    int main() {
        ios::sync_with_stdio(false);
        cin >> n >> m;
        for (ll i = 1; i <= m; i++) {
            ll u, v, w;
            cin >> u >> v >> w;
            e[i].u = u;
            e[i].v = v;
            e[i].w = w;
        }
        sort(e + 1, e + m + 1);
        for (ll i = 1; i <= n; i++) fa[i] = i;
        for (ll i = 1; i <= m; i++) {
            ll p = find(e[i].u), q = find(e[i].v);
            if (p != q) {
                merge(p, q);
                ans += e[i].w;
                g[e[i].u].push_back(make_pair(e[i].v, e[i].w));
                g[e[i].v].push_back(make_pair(e[i].u, e[i].w));
            }
        }
        for (ll i = 1; i <= n; i++) {
            memset(vis, 0, sizeof vis);
            dfs(i, i);
        }
        ll delta = 1e+9;
        for (ll i = 1; i <= m; i++)
            if (e[i].w - h[e[i].u][e[i].v] > 0) {
                delta = min(delta, e[i].w - h[e[i].u][e[i].v]);
            }
        cout << ans + delta << endl;
    }
    

    10069. 「一本通 3.1 练习 4」Tree

    显然具有可二分性

    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll n, m, k, fa[100005];
    double ans;
    ll find(ll p) { return p == fa[p] ? p : (fa[p] = find(fa[p])); }
    void merge(ll p, ll q) {
        p = find(p);
        q = find(q);
        if (p > q)
            swap(p, q);
        fa[q] = p;
    }
    struct Edge {
        ll u, v, c;
        double w;
        bool operator<(const Edge &b) { return w < b.w; }
    } e[100005];
    
    int mst() {
        ans = 0;
        int cnt = 0;
        sort(e + 1, e + m + 1);
        for (ll i = 1; i <= n; i++) fa[i] = i;
        for (ll i = 1; i <= m; i++) {
            if (find(e[i].u) == find(e[i].v))
                continue;
            ans += e[i].w;
            cnt += e[i].c;
            merge(e[i].u, e[i].v);
        }
        return cnt;
    }
    int s[100005], t[100005], c[100005], col[100005];
    int main() {
        ios::sync_with_stdio(false);
        cin >> n >> m >> k;
        for (int i = 1; i <= m; i++) cin >> s[i] >> t[i] >> c[i] >> col[i], ++s[i], ++t[i];
        double l = -1000, r = 1000;
        int cnt;
        while (r - l > 1e-6) {
            double mid = (l + r) / 2.0;
            for (int i = 1; i <= m; i++)
                e[i].u = s[i], e[i].v = t[i], e[i].c = col[i], e[i].w = c[i] + (double)(col[i]) * mid;
            if (mst() > n - k - 1)
                l = mid;
            else
                r = mid;
        }
        cout << (int)(ans - l * (n - k - 1) + 0.01) << endl;
    }
    
  • 相关阅读:
    互质与欧拉函数学习笔记
    Luogu P4588 [TJOI2018]数学计算 题解
    Luogu P1072 Hankson 的趣味题 题解
    Luogu [POI2002][HAOI2007]反素数 题解
    Luogu P2986 [USACO10MAR]伟大的奶牛聚集Great Cow Gat… 题解
    JavaScript 实现简易版贪吃蛇(Day_13)
    IDEA 配置 Tomcat(详细)(Day_12)
    常用数据库连接池配置及使用(Day_11)
    大对象数据LOB的应用(Day_10)
    IDEA中配置maven 全解析教程(Day_08)
  • 原文地址:https://www.cnblogs.com/mollnn/p/11614175.html
Copyright © 2020-2023  润新知