• [题解] uva 1151 Buy or Build (kruskal最小生成树)


    - 传送门 -

     https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3592

    # 1151 - Buy or Build Time limit: 3.000 seconds | [Root](https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=0) | [![Submit](https://uva.onlinejudge.org/components/com_onlinejudge/images/button_submit.png "Submit")](https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=submit_problem&problemid=3592&category=) [![Problem Stats](https://uva.onlinejudge.org/components/com_onlinejudge/images/button_stats.png "Problem Stats")](https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=problem_stats&problemid=3592&category=) [![uDebug](https://uva.onlinejudge.org/components/com_onlinejudge/images/button_debug.png)](https://www.udebug.com/UVa/1151) [![Download as PDF](https://uva.onlinejudge.org/components/com_onlinejudge/images/button_pdf.png "Download as PDF")](https://uva.onlinejudge.org/external/11/1151.pdf) | ###(题面见pdf)
      ### - 题意 -  有n个节点(给出坐标), 在两节点间建边的代价为它们距离的平方, 同时有q个套餐,每个套餐有一个价格和若干个点. 付出套餐价即可使套餐中所有点联通(买套餐的数量没有限制).  求出使所有点联通的最小代价.   ### - 思路 -  考虑套餐数量很小( <= 8 ), 可以用二进制枚举, 枚举 $1$ 到 $2^q-1$, 若第k位上是1, 则取第 k 种套餐.  把取到的套餐中的点都联通之后, 再进行一次kruskal求出总代价.    细节见代码.    PS:  因为要二进制枚举, 套餐我是从0开始标记的, 但手残把点也改成从 0 开始标记了(因为记录套餐时是默认节点从1开始的), 然后调啊调...   ### - 代码 - ```c++ #include #include #include #include using namespace std;

    const int N = 1000 + 5;
    const int inf = 0x7fffffff;

    struct edge {
    int x, y, v;
    }W[N*N];

    int F[N], X[N], Y[N], C[10];
    int cnt, cst, ans, n, m, T, sz;

    vector S[10];

    bool cmp (edge a, edge b) { return a.v < b.v; }

    int distance(int a, int b) {
    return (X[a] - X[b]) * (X[a] - X[b]) + (Y[a] - Y[b]) * (Y[a] - Y[b]);
    }

    int find(int x) { return F[x] == x ? x : F[x] = find(F[x]); }

    int merge(int a, int b) {
    int xf = find(a), yf = find(b);
    if (xf == yf) return 0;
    F[xf] = yf;
    cnt ++;
    return 1;
    }

    int kruskal() {
    int tot = 0;
    for (int i = 1, tmp; i <= sz; ++i) {
    tmp = merge(W[i].x, W[i].y);
    if (tmp) tot += W[i].v;
    if (cnt == n - 1) break; //注意cnt的初始化
    }
    return tot;
    }

    void init() {
    cnt = cst = 0;
    for (int i = 0; i <= n; ++i)
    F[i] = i;
    }

    int main() {
    scanf("%d", &T);
    for (int cas = 0; cas < T; ++cas) {
    if (cas) printf(" "); //uva诡异的输出
    sz = cnt = 0;
    scanf("%d%d", &n, &m);
    for (int i = 0, ct, tmp; i < m; ++i) {
    scanf("%d%d", &ct, &C[i]);
    S[i].clear();
    for (int j = 1; j <= ct; ++j) {
    scanf("%d", &tmp);
    S[i].push_back(tmp);
    }
    }
    for (int i = 1; i <= n; ++i) {
    scanf("%d%d", &X[i], &Y[i]);
    for (int j = 1; j < i; ++j) {
    W[++sz].x = j; W[sz].y = i;
    W[sz].v = distance(i, j);
    }
    }
    sort(W + 1, W + sz + 1, cmp);
    init();
    ans = kruskal();//不买套餐的情况
    for (int i = 1; i < (1 << m); ++i) {
    init();//初始化
    for (int j = 0; j < m; ++j) {
    if (i & (1 << j)) {
    for (int k = 1, tmp; k < S[j].size(); ++k)
    tmp = merge(S[j][k], S[j][0]);
    cst += C[j];
    }
    }
    int aa = kruskal();
    ans = min(ans, cst + aa);
    }
    printf("%d ", ans);
    }
    }

  • 相关阅读:
    kotlin 通过 下标比对
    textarea元素调整
    jquery给两个标签绑定一个事件
    开发过程中遇到的错误
    response.setHeader各种用法详解
    如何在eclipse里删除一个类 然后SVN服务器也同时删了这个类
    @pathvariable 与@requestparam 写rest接口时遇到的
    $.getJSON
    easyUI学习
    jQuery validator addMethod 动态提示信息
  • 原文地址:https://www.cnblogs.com/Anding-16/p/7354759.html
Copyright © 2020-2023  润新知