UVa #1151 Buy or Build (例题11-3)

来源:互联网 发布:js获取所有id 像 编辑:程序博客网 时间:2024/06/05 01:58

套餐只有8个,可以暴力枚举。不过边太多,不能枚举套餐都求一遍最小生成树。


其实只需要在一开始求出不包含套餐的最小生成树,把这些边记下来备用。之后枚举套餐的时候,先把套餐中的点全部加入并查集,然后在原最小生成树的基础上,再来求最小生成树就可以了。


那些一开始就没有被加入最小生成树的边,到了暴力枚举又加入很多权值为0的边排在他们前面,就更加不会被包含到最小生成树中了。



Run Time: 0.245s

#define UVa  "LT11-3.1151.cpp"      //Buy or Build#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<iostream>using namespace std;//Global Variables.const int maxn = 1000 + 5, maxe = maxn*maxn, maxq = 10;int T, n, q, m;int x[maxn], y[maxn];int u[maxe], v[maxe], w[maxe], r[maxe];int qsize[maxq], qcost[maxq], qcities[maxq][maxn];vector<int> min_span_tree;int p[maxn];int ans;////int cmp(int a, int b) { return w[a] < w[b]; }int calc_w(int a, int b) { return (x[a]-x[b])*(x[a]-x[b]) + (y[a]-y[b])*(y[a]-y[b]); }int find(int s) {               //union-find set    int t = s;    while(s != p[s]) s = p[s];    while(p[t] != s) {          //change p along the path        int tmp = p[t];        p[t] = s;        t = tmp;    }    return s;}void kruscal() {    min_span_tree.clear();    ans = 0;    for(int i = 0; i < m; i ++) {        int e = r[i];        int x = find(u[e]), y = find(v[e]);        if(x != y) {        //include in min-span tree.            p[x] = y;            ans += w[e];            min_span_tree.push_back(e);        }    }}void print_bin(int a) {    for(int i = 0; i < q; i ++) {        printf("%d", a%2);        a/=2;    }    printf("\n");}int solve() {    for(int s = 1; s < (1<<q); s ++) {      //iterating all existing networks.        int tmp = 0;        for(int i = 1; i <= n; i ++) p[i] = i;      //reset union-find set.        for(int k = 0; k < q; k ++) if((1<<k) & s){            tmp += qcost[k];            for(int i = 0; i < qsize[k]; i ++){                for(int j = i+1; j < qsize[k]; j ++){                    int x = find(qcities[k][i]), y = find(qcities[k][j]);                    if(x != y) p[x] = y;                }            }        }        for(int i = 0; i < min_span_tree.size(); i ++) {            int e = min_span_tree[i];            int x = find(u[e]), y = find(v[e]);            if(x != y) {                p[x] = y;                tmp += w[e];            }        }        ans = min(ans, tmp);    }    return 0;}int main(){    scanf("%d", &T);    while(T--) {        scanf("%d%d", &n, &q);        for(int i = 0; i < q; i ++) {            scanf("%d%d", &qsize[i], &qcost[i]);            for(int j = 0; j < qsize[i]; j ++)                scanf("%d", &qcities[i][j]);        }        for(int i = 1; i <= n; i ++) {            scanf("%d%d", &x[i], &y[i]);            p[i] = i;        }        m = 0;        for(int i = 1; i <= n; i ++) {            for(int j = i+1; j <= n; j ++) {                r[m] = m;                u[m] = i;                v[m] = j;                w[m] = calc_w(i, j);                m ++;            }        }        sort(r, r+m, cmp);        kruscal();        solve();        printf("%d\n", ans);        if(T) printf("\n");    }    return 0;}

1 0
原创粉丝点击