[UVA - 1151] Buy or Build 题解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[UVA - 1151] Buy or Build 题解相关的知识,希望对你有一定的参考价值。

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。

题目链接(vjudge):https://vjudge.net/problem/UVA-1151

题目大意:

要把n个城市用网络连接起来。直接或间接连通均可。

每次你可以选择新建一条网络连接两个城市,花费为这两个城市的欧几里得距离。

你也可以选择购买一份已有的网络套餐,花费为Ci元,套餐内的所有城市都会连通。

问最少需要花费多少元。

第一行有一个数T,表示数据组数。

接下来每组数据,第一行有两个数n,k,表示城市数量和套餐数量。(1<=n<=1000,0<=k<=8)

第二行至第k+1行,描述套餐的相关数据。

每行第一个数m表示该套餐内的城市数,第二个数Ci表示该套餐的价格,接下来m个数表示该套餐内的城市。

第k+2行到第k+2+n行,每行两个整数x,y,表示第i个城市的坐标。

输出时,每行输出一个答案,两个答案之间空一行。最后一个答案不空行。

这个辣鸡输出格式要求害我改了好久。辣鸡样例只有一组数据,根本看不出输出要求。

而且如果你少换行了是有可能WA的(我的提交记录一次PE一次WA,但其实都是PE),就很难查错...

 

Sample Input
1
7 3
2 4 1 2
3 3 3 6 7
3 9 2 4 5
0 2
4 0
2 0
4 2
1 3
0 5
4 4
Sample Output
17

 

分析:

在没有套餐的情况下求一次最小生成树,然后枚举每一份套餐选不选,把套餐的边加进去,重新做最小生成树。

所有情况的费用取Min更新答案即可。

k不超过8,枚举时用二进制表示当前套餐是否使用。

复杂度O(nlogn+n*2^k)。

 

AC代码:(惨烈的Debug痕迹..)

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<iostream>
  6 
  7 inline void read(int &x)
  8 {
  9     char ch = getchar(),c = ch;x = 0;
 10     while(ch < 0 || ch > 9) c = ch,ch = getchar();
 11     while(ch <= 9 && ch >= 0) x = (x<<1)+(x<<3)+ch-0,ch = getchar();
 12     if(c == -) x = -x;
 13 }
 14 
 15 int Case,n,m,k,v,cnt,fa[1002];
 16 long long ans;
 17 
 18 inline int find(int x)
 19 {return fa[x]==x?x:fa[x]=find(fa[x]);}
 20 
 21 bool merge(int x,int y)
 22 {
 23     x = find(x),y = find(y);
 24     if(x != y)
 25     {
 26         fa[x] = y;
 27         return true;
 28     }
 29     return false;
 30 }
 31 
 32 inline long long Min(long long x,long long y)
 33 {return x<y?x:y;}
 34 
 35 struct SET
 36 {
 37     int m,cost;
 38     int mem[1002];
 39 }s[10];
 40 
 41 struct CITY
 42 {
 43     int x,y,v;
 44 }c[1002],e[1000002],New[1002];
 45 
 46 int cmp(CITY a,CITY b)
 47 {return a.v < b.v;}
 48 
 49 int dis(int i,int j)
 50 {
 51     int r = (c[i].x-c[j].x)*(c[i].x-c[j].x);
 52     r += (c[i].y-c[j].y)*(c[i].y-c[j].y);
 53     return r;
 54 }
 55 
 56 void init()
 57 {
 58     cnt = 0;ans = 0;
 59     for(int i=1;i<=n;++i) fa[i] = i;
 60 }
 61 
 62 int main()
 63 {
 64 //    freopen("1.txt","r",stdin);
 65     read(Case);
 66     while(Case --)
 67     {
 68         read(n),read(k);
 69         init();
 70         for(int i = 1;i <= k;++ i){
 71             read(s[i].m),read(s[i].cost);
 72             for(int j = 1;j <= s[i].m;++ j)
 73                 read(s[i].mem[j]);
 74         }
 75         for(int i = 1;i <= n;++ i)
 76             read(c[i].x),read(c[i].y);
 77         for(int i = 1;i <= n;++ i)
 78             for(int j = i+1;j <= n;++ j)
 79             {
 80                 v = dis(i,j);
 81                 e[++cnt] = (CITY){i,j,v};
 82             }
 83         std::sort(e+1,e+1+cnt,cmp);
 84         m = cnt;cnt = 0;
 85 //        for(int i = 1;i <= m;++ i)
 86 //            printf("%d %d %d \n",e[i].x,e[i].y,e[i].v);
 87         for(int i = 1;i <= m;++ i)
 88         {
 89             if(merge(e[i].x,e[i].y)){
 90                 ans += 1LL*e[i].v,cnt ++;
 91                 New[cnt] = e[i];
 92             }
 93             if(cnt == n-1) break;
 94         }
 95         for(int tmp = 0;tmp < (1<<k);++ tmp)
 96         {
 97             long long cost = 0;
 98             for(int i = 1;i <= n;++ i) fa[i] = i;
 99             
100             for(int i = 0;i < k;++ i)
101                 if(tmp&(1<<i)){
102                     cost += 1LL*s[i+1].cost;
103                     for(int j = 2;j <= s[i+1].m;++ j)
104                         fa[find(s[i+1].mem[j-1])] = fa[find(s[i+1].mem[j])];
105                 }
106             for(int i = 1;i < n;++ i)
107                 if(merge(New[i].x,New[i].y))
108                     cost += 1LL*New[i].v;
109             ans = Min(ans,cost);
110 //            printf("%d\n",cost);            
111         }
112         printf("%lld\n",ans);
113         if(Case) printf("\n");
114     }
115     return 0;
116 }

 

以上是关于[UVA - 1151] Buy or Build 题解的主要内容,如果未能解决你的问题,请参考以下文章

[UVA - 1151] Buy or Build 题解

UVa 1151 - Buy or Build(最小生成树)

UVa1151 Buy or Build (最小生成树,枚举子集)

uva 1151Buy or Build(图论 最小生成树)

UVa 1151 Buy or Build (最小生成树+二进制法暴力求解)

UVA 1151 Buy or Build (有某些特别的东东的最小生成树)