2 solutions

  • 1
    @ 2024-10-16 0:05:11
    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 25, inf = 0x3f3f3f3f;
    
    int g[N][N], dist[N];
    int tr[N][N], pre[N]; // tr最小生成树的矩阵,pre[y] = x: (x - > y) tr[y][pre[y]];
    int n, m, ans, s, deg;
    int f[N], fx[N], fy[N]; // 以某个点为子树的树边的最大值为f[i], 这条边连接的点为(fx[i], fy[i])
    bool v[N], c[N];
    vector<int> con;
    unordered_map<string, int> h;
    
    int get(string x) {
        if(!h[x]) h[x] = ++ n;
        return h[x];
    }
    
    void prim() { // 求最小生成树
        dist[con[0]] = 0;
        for(int i = 0; i < con.size(); i ++ ) {
            int x = 0;
            for(int j = 0; j < con.size(); j ++ ) 
                if(!v[con[j]] && (x == 0 || dist[x] > dist[con[j]])) x = con[j];
            v[x] = true;
            ans += dist[x];
            for(int y = 0; y < con.size(); y ++ ) 
                if(!v[con[y]] && dist[con[y]] > g[x][con[y]]) dist[con[y]] = g[x][con[y]], pre[con[y]] = x;
        }
        int mini = con[0];
        for(int i = 1; i < con.size(); i ++ ) {
            int x = con[i];
            tr[pre[x]][x] = tr[x][pre[x]] = dist[x];
            if(g[1][mini] > g[1][x]) mini = x;
        }
        deg ++ ;
        ans += g[1][mini];
        tr[1][mini] = tr[mini][1] = g[1][mini];
    }
    
    void dfs(int x) {
        c[x] = true;
        con.push_back(x);
        for(int i = 2; i <= n; i ++ ) 
            if(!c[i] && g[x][i] < 0x3f3f3f3f) dfs(i);
    }
    
    void con_prim() {
        memset(tr, 0x3f, sizeof tr);
        memset(dist, 0x3f, sizeof dist);
        c[1] = true;
        for(int i = 2; i <= n; i ++ ) {
            if(!c[i]) {
                con.clear();
                dfs(i);
                prim();
            }
        }
    }
    
    void dp(int x) {
        c[x] = true;
        for(int y = 1; y <= n; y ++ ) 
            if(!c[y] && tr[x][y] < inf) {
                if(tr[x][y] < f[x]) {
                    f[y] = f[x];
                    fx[y] = fx[x], fy[y] = fy[x];
                }
                else {
                    f[y] = tr[x][y];
                    fx[y] = x, fy[y] = y;
                }
                dp(y);
            }
        c[x] = false;
    }
    
    bool solve() { //  删除输边,加非树边的操作
        int min_edge = inf, mini;
        for(int i = 2; i <= n; i ++ ) {
            if(tr[1][i] < 0x3f3f3f3f || g[1][i] == inf) continue;
            if(g[1][i] - f[i] < inf && min_edge > g[1][i] - f[i]) {
                min_edge = g[1][i] - f[i];
                mini = i;
            }
        }
        if(min_edge >= 0) return false;
        ans += min_edge;
        deg ++ ;
        tr[1][mini] = tr[mini][1] = g[1][mini];
        tr[fx[mini]][fy[mini]] = tr[fy[mini]][fx[mini]] = inf;
        f[mini] = g[1][mini];
        fx[mini] = 1, fy[mini] = mini;
        dp(mini);
        return true;
    }
    
    int main() {
        cin >> m;
        get("Park");
        memset(g, 0x3f, sizeof g);
        for(int i = 0; i < m; i ++ ) {
            int x, y, z;
            string a, b;
            cin >> a >> b >> z;
            x = get(a), y = get(b);
            g[x][y] = g[y][x] = min(g[x][y], z);
        }
        cin >> s;
        con_prim(); // O(n ^ 2)
        memset(c, 0, sizeof c);
        dp(1); // 以某个点为根的子树的树边的最大值
        while(deg < s) { // O(n ^ 4)
            if(!solve()) break;
        }
        cout << "Total miles driven: " << ans << endl;
        return 0;
    }
    
    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 25, inf = 0x3f3f3f3f;
    
    int g[N][N], dist[N];
    int tr[N][N], pre[N]; // tr最小生成树的矩阵,pre[y] = x: (x - > y) tr[y][pre[y]];
    int n, m, ans, s, deg;
    bool v[N];
    unordered_map<string, int> h;
    
    int get(string x) {
        if(!h[x]) h[x] = ++ n;
        return h[x];
    }
    
    void prim() { // 求最小生成树
        memset(dist, 0x3f, sizeof dist);
        dist[1] = 0;
        for(int i = 0; i < n; i ++ ) {
            int x = 0;
            for(int j = 1; j <= n; j ++ ) 
                if(!v[j] && (x == 0 || dist[x] > dist[j])) x = j;
            v[x] = true;
            ans += dist[x];
            for(int y = 1; y <= n; y ++ ) 
                if(!v[y] && dist[y] > g[x][y]) dist[y] = g[x][y], pre[y] = x;
        }
        memset(tr, 0x3f, sizeof tr);
        for(int x = 1; x <= n; x ++ ) {
            if(pre[x] == 1) deg ++ ;
            tr[pre[x]][x] = tr[x][pre[x]] = dist[x];
        }
    }
    
    void dfs(int x) {
        v[x] = true;
        for(int i = 2; i <= n; i ++ ) 
            if(!v[i] && tr[x][i] < 0x3f3f3f3f) dfs(i);
    }
    
    int find_min(int &x, int &y) { // 找最小边
        int min_edge = 0x3f3f3f3f;
        for(int i = 2; i <= n; i ++ ) if(!v[i])
            for(int j = 2; j <= n; j ++ ) if(v[j]) 
                if(min_edge > g[i][j]) {
                    min_edge = g[i][j];
                    x = i, y = j;
                }
        return min_edge;
    }
    
    void solve() { //  删除输边,加非树边的操作
        int min_edge = inf, minx, miny, mini;
        for(int i = 2; i <= n; i ++ ) {
            if(tr[1][i] == 0x3f3f3f3f) continue;
            memset(v, 0, sizeof v);
            v[1] = true;
            dfs(i);
            int x, y;
            int add_edge = find_min(x, y);
            if(add_edge < inf && min_edge > add_edge - tr[1][i]) {
                minx = x, miny = y, mini = i;
                min_edge = add_edge - tr[1][i];
            }
        }
        ans += min_edge;
        deg -- ;
        tr[1][mini] = tr[mini][1] = inf;
        tr[minx][miny] = tr[miny][minx] = g[minx][miny];
    }
    
    int main() {
        cin >> m;
        get("Park");
        memset(g, 0x3f, sizeof g);
        for(int i = 0; i < m; i ++ ) {
            int x, y, z;
            string a, b;
            cin >> a >> b >> z;
            x = get(a), y = get(b);
            g[x][y] = g[y][x] = min(g[x][y], z);
        }
        cin >> s;
        prim();
        while(deg > s) {
            solve();
        }
        cout << "Total miles driven: " << ans << endl;
        return 0;
    }
    

    Information

    ID
    504
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    10
    Tags
    # Submissions
    3
    Accepted
    2
    Uploaded By