zoukankan      html  css  js  c++  java
  • [一本通学习笔记] 最小生成树

    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;
    }
    
  • 相关阅读:
    Leetcode 1489找到最小生成树李关键边和伪关键边
    Leetcode 113 路径总和 II
    hdu 1223 还是畅通工程
    hdu 1087 Super Jumping! Jumping! Jumping!
    hdu 1008 Elevator
    hdu 1037 Keep on Truckin'
    湖工oj 1241 畅通工程
    湖工oj 1162 大武汉局域网
    hdu 2057 A + B Again
    poj 2236 Wireless Network
  • 原文地址:https://www.cnblogs.com/mollnn/p/11614175.html
Copyright © 2011-2022 走看看