zoukankan      html  css  js  c++  java
  • POJ 1639度限制生成树

    题目就是给出一些英文名称, 并且要求源点为park的入度不能超过k
    给出思路:
    1.首先抹去park, 在剩下的连通分量中求出最小生成树加入答案, 此时的度是最小的, 即如果现在的度大于k, 则无解(题目好像没这个情况)
    2.由于我们一开始删去了和park相邻的每一条边, 所以我们要加上每个联通子图到park的最小边, 但这样并不是最好的, 我们要把度加到k, 这样会使答案更优(至于具体的操作, 留一点思考的空间, 也可以看我的代码)

    #include <map>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int N = 150;
    const int oo = 0x3f3f3f;
    #define FILL(a, b) memset(a, b, sizeof(a))
    #define rep(i, s, t) for(int i = s; i <= t; ++i)
    
    map<string, int> id;
    int insert(string s) {
        if(!id.count(s)) id[s] = id.size();
        return id[s];
    }
    
    struct Edge {
        int u, v, w;
    }p[N];
    
    struct Part_Prim {
        int G[N][N], n, m, limit, fa[N];
        int dis[N], vis[N], cnt, used[N][N];
        void init() {
            id.clear(); id["Park"] = 1; cnt = 0;
            rep(i, 1, N-1) rep(j, 1, N-1) G[i][j] = oo;
            FILL(vis, 0), FILL(used, 0), FILL(p, 0);
        }
    
        int prim(int s, int ret = 0, int add = oo) {
            int to_root = 0; ++cnt;
            rep(i, 0, n) dis[i] = oo;
            dis[s] = 0;
            rep(i, 1, n-1) {
                int k = 0;
                rep(j, 2, n) if(dis[k] > dis[j] && !vis[j]) k = j;
                if(!k) break;
                ret += dis[k]; vis[k] = cnt;
                if(add > G[k][1]) to_root = k, add = G[k][1];
    
                rep(j, 2, n) 
                    if(G[k][j] < dis[j] && !vis[j]) 
                        dis[j] = G[k][j], fa[j] = k;
                if(fa[k]) used[k][fa[k]] = used[fa[k]][k] = 1;
            }
            used[1][to_root] = used[to_root][1] = 1;
            return ret + add;
        }
    
        void dfs(int u, int f) {
            rep(v, 2, n)
                if(used[u][v] && v ^ f) {
                    p[v] = p[u];
                    if(G[u][v] ^ oo && G[u][v] > p[v].w)
                        p[v] = (Edge) {u, v, G[u][v]};
                    dfs(v, u);
                }
        }
    
        int parking(int ret = 0, int t = 0) {
            rep(i, 2, n) if(!vis[i]) ret += prim(i);
    //      cout << ret << endl;
            while(cnt++ < limit) {
                dfs(1, 0);
                rep(i, 2, n) 
                    if(G[1][i] ^ oo && !used[1][i] && p[i].w-G[1][i] > p[t].w-G[1][t]) 
                        t = i;
                ret -= p[t].w-G[1][t]; 
    //          cout << p[t].w << "!" << endl;
                used[1][t] = used[t][1] = 1;
                used[p[t].u][p[t].v] = used[p[t].v][p[t].u] = 0;
            }
            return ret;
        }
    
        void solve(int _ = 0) {
            while(~scanf("%d", &_)) {
                init();
                while(_--) {
                    string s1, s2; int w, u, v;
                    cin >> s1 >> s2 >> w;
                    u = insert(s1), v = insert(s2);
                    G[u][v] = G[v][u] = w;
                }
                n = id.size();
                scanf("%d", &limit);
                printf("Total miles driven: %d
    ", parking());
            }
        }
    }WORK;
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("IP.in", "r", stdin);
        freopen("OP.out", "w", stdout);
    #endif
        WORK.solve();
        return 0;
    }
  • 相关阅读:
    Leetcode Binary Tree Level Order Traversal
    Leetcode Symmetric Tree
    Leetcode Same Tree
    Leetcode Unique Paths
    Leetcode Populating Next Right Pointers in Each Node
    Leetcode Maximum Depth of Binary Tree
    Leetcode Minimum Path Sum
    Leetcode Merge Two Sorted Lists
    Leetcode Climbing Stairs
    Leetcode Triangle
  • 原文地址:https://www.cnblogs.com/pbvrvnq/p/8530156.html
Copyright © 2011-2022 走看看