题意:

  要使n个点之间能够互通,要使两点直接互通需要耗费它们之间的欧几里得距离的平方大小的花费,这说明每两个点都可以使其互通。接着有q个套餐可以选,一旦选了这些套餐,他们所包含的点自动就连起来了,所需要做的就是连上还未通的即可,q<=8。可以多买。求最小生成树所需的代价。

思路:

  与普通求MST不同的就是多了套餐,而且还可以多买。每个套餐有买或不买两种可能,那么有28种可能,即256种。

  如果不买套餐,至少需要求1次MST是确定的,这个复杂度已经是O(n*n)了。还得考虑哪些餐套可以搭配来买更便宜,那么就穷举这256种组合,每种组合来一次MST,但是不再需要O(n*n)了,只需要用第一次生成树时所挑出来的边即可。

  具体做法是,将套餐内的所有点先连接(并查集),再用MST的边来一次kruscal(记得加上套餐费)。对于每个组合都这样做,就能求出结果了。

  特别要注意:每两个输出结果之间要1个空行,末尾不需要再空行,否则出错。

 #include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=+;
const int INF=0x7f7f7f7f;
vector<int> vect[];
vector< pair<int,int> > cor, e, tree;
int t, r, n, q, a, b;
int cost[], pre[N], g[N][N];; int cmp(pair<int,int> a,pair<int,int> b){return g[a.first][a.second]<g[b.first][b.second]? true: false;}//按照距离来排序
int dis( pair<int,int> a,pair<int,int> b ){return (a.first-b.first)*(a.first-b.first) +(a.second-b.second)*(a.second-b.second) ;}//不需要开方 int find(int x){return pre[x]==x? x: pre[x]=find(pre[x]);} //查
void joint(int a,int b){a=find(a),b=find(b);if(a!=b) pre[a]=b;} //并 LL kruscal() //将生成树的树边取出
{
for(int i=; i<=n; i++) pre[i]=i;
int cnt=;
LL sum=;
for(int i=; i<e.size(); i++)
{
int a=e[i].first;
int b=e[i].second;
if(find(a)!=find(b))
{
cnt++;
tree.push_back(e[i]); //收藏边
sum+=g[a][b]; //统计权值
joint(a,b); //a和b是点
if(cnt>=n-) return sum;
}
}
return sum;
} LL kruscal_2() //带套餐的
{
LL sum=;
for(int i=; i<tree.size(); i++)
{
int a=tree[i].first;
int b=tree[i].second;
if(find(a)!=find(b))
{
sum+=g[a][b];
joint(a,b);
}
}
return sum;
} LL cal()
{
sort(e.begin(), e.end(), cmp);
tree.clear();
LL ans=kruscal(); //第一次生成树,挑出有用边
int choice=;
while(q--) choice+=choice;
for(int i=; i<choice; i++)
{
for(int j=; j<=n; j++) pre[j]=j;
int tmp=i, cnt=;
LL sum=;
while(tmp) //先将欲买套餐的pre归类
{
if((tmp&)==) //第cnt个套餐要了
{
sum+=cost[cnt];
for(int j=; j<vect[cnt].size(); j++) joint(vect[cnt][j-],vect[cnt][j]);
}
tmp>>=;
cnt++;
}
ans=min(ans, sum+kruscal_2()); //再生成树
}
return ans;
} int main()
{
freopen("input.txt", "r", stdin);
cin>>t;
while(t--)
{
cin>>n>>q;
for(int i=; i<=q; i++) //每个套餐
{
scanf("%d%d",&a,&cost[i]);
vect[i].clear();
while(a--)
{
scanf("%d",&r);
vect[i].push_back(r);
}
}
cor.clear();
for(int i=; i<n; i++)
{
scanf("%d%d",&a,&b);
cor.push_back(make_pair(a,b)); //每个点的坐标
} memset(g, , sizeof(g));
e.clear();
for(int i=; i<=n; i++) //计算出距离
{
for(int j=i+; j<=n; j++)
{
g[i][j]=g[j][i]= dis(cor[i-],cor[j-]);
e.push_back(make_pair(i,j));
}
}
cout<<cal()<<endl;
if(t) printf("\n");
}
return ;
}

AC代码

UVA 1151 Buy or Build (MST最小生成树,kruscal,变形)的更多相关文章

  1. UVA 1151 Buy or Build MST(最小生成树)

    题意: 在平面上有n个点,要让所有n个点都连通,所以你要构造一些边来连通他们,连通的费用等于两个端点的欧几里得距离的平方.另外还有q个套餐,可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相 ...

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

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

  3. UVA 1151 Buy or Build (最小生成树)

    先求出原图的最小生成树,然后枚举买哪些套餐,把一个套餐内的点相互之间边权为0,直接用并查集缩点.正确性是基于一个贪心, 在做Kruskal算法是,对于没有进入最小生成树的边,排序在它前面的边不会减少. ...

  4. UVa 1151 Buy or Build【最小生成树】

    题意:给出n个点的坐标,现在需要让这n个点连通,可以直接在点与点之间连边,花费为两点之间欧几里得距离的平方,也可以选购套餐,套餐中所含的点是相互连通的 问最少的花费 首先想kruskal算法中,被加入 ...

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

    题意:给定n个点,你的任务是让它们都连通.你可以新建一些边,费用等于两点距离的平方(当然越小越好),另外还有几种“套餐”,可以购买,你购买的话,那么有些边就可以连接起来, 每个“套餐”,也是要花费的, ...

  6. uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)

    最小生成树算法简单 只是增加了一些新的东西,对于需要最小生成树算法 和中 并检查使用的一系列 还有一些更深入的了解. 方法的一些复杂问题 #include<cstdio> #include ...

  7. UVA - 1151 Buy or Build (买还是建)(并查集+二进制枚举子集)

    题意:平面上有n个点(1<=n<=1000),你的任务是让所有n个点连通.可以新建边,费用等于两端点欧几里德距离的平方.也可以购买套餐(套餐中的点全部连通).问最小费用. 分析: 1.先将 ...

  8. 紫书 例题 11-3 UVa 1151 (有边集的最小生成树+二进制枚举子集)

    标题指的边集是说这道题的套餐, 是由几条边构成的. 思路是先做一遍最小生成树排除边, 因为如果第一次做没有加入的边, 到后来新加入了很多权值为0的边,这些边肯定排在最前面,然后这条边的前面的那些边肯定 ...

  9. UVA 1151 买还是建(最小生成树)

    买还是建 紫书P358 [题目链接]买还是建 [题目类型]最小生成树 &题解: 这题真的心累,看了3天,最后照着码还是wa,先放lrj代码,以后再看吧 &代码: // UVa1151 ...

随机推荐

  1. Intellij IDEA14 下添加ExtJS提示支持

    前言: 虽然Interlij IDEA比起Eclipse对待EXT更为支持,但自己上手后总不能达到Intellij 开发ExtJS 应用指南(http://blog.csdn.net/s4640368 ...

  2. uva 11609

    可以想到 答案为 1*C(1,n)+2*C(2,n)+3*C(3,n)+....+n*C(n,n); 由公式 k*C(k,n) = n*C(k-1,n-1) 所以最终答案 n*2^(n-1) 用到快速 ...

  3. Eclipse Error: Unable to set localhost. This prevents creation of a GUID.

    Symptoms The following error appears in the atlassian-confluence.log: 2011-03-16 18:20:03,021 ERROR ...

  4. Namespace, string, vector and array

    1. Headers should not include using declaration Code inside headers ordinarily should not include us ...

  5. Android 动画的重复播放

    如果你要的加载xml方式设置动画,而且在xml定义了好几个动画元素比如:<set>    <alpha android:repeatCount="-1" andr ...

  6. Ubuntu 12.04LTS 找不到eth0网卡

    我的机器是DELL 14R INSPRION 7420 笔记本.试了好多方法都不行,比如这个教程: . sudo ifconfig -a //查看所有网卡现状,看eth0是否存在,在结果列表应该找不到 ...

  7. SaaS系列介绍之十五: SaaS知识重用

    1 建立并积累自己的开发体系 遵行业界的规定又有自己的特色是我们所追求的目标.成功的软件公司都有丰富而可复用的代码组件,几行代码在单个系统里可能无足轻重,但一旦可在大量的系统中可重复使用那就是价值不菲 ...

  8. 【Linux高频命令专题(22)】gzip

    概述 减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间.gzip是在Linux系统中经常使用的一个对文件进行压缩和解压缩的命令,既方便又好用.gzip不仅 ...

  9. Linux系统与性能监控

    原文地址:http://kerrigan.sinaapp.com/post-7.html Linux System and Performance Monitoring http://www.hous ...

  10. 龙芯将两款 CPU 核开源,这意味着什么?

    10月21日,教育部计算机类教学指导委员会.中国计算机学会教育专委会将2016 CNCC期间在山西太原举办“面向计算机系统能力培养的龙芯CPU高校开源计划”活动,在活动中,龙芯中科宣布将GS132和G ...