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;
    }
  • 相关阅读:
    一个word小技巧
    Android 自定义组件之 带有悬浮header的listview
    传智播客 java基础 相关资料 Day2
    js取整 摘抄
    ifram子页面父页面相互调用
    寻知图项目收获--项目管理方面
    圣经学习 读经群读经记录(一)申命记5-7章
    java1234教程系列笔记 S1 Java SE chapter 02 写乘法口诀表
    java1234教程系列笔记 S1 Java SE chapter 02 lesson 03 java基本数据类型
    java1234教程系列笔记 S1 Java SE 02 eclipse初步使用、注释、标识符
  • 原文地址:https://www.cnblogs.com/pbvrvnq/p/8530156.html
Copyright © 2011-2022 走看看