题意:

  要使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. 关于struts2如何去掉默认的后缀(.action)

    struts2是可以配置默认的后缀名的,如http://localhost:8080/test.action,这个是默认的,但是也可以通过配置去修改这个.action为别的. 这里是通过一个常量配置改 ...

  2. linux下如何导入导出MySQL数据库

    一.导出:用mysqldump命令行命令格式mysqldump -u 用户名 -p 数据库名 > 数据库名.sql范例:mysqldump -u root -p abc > abc.sql ...

  3. Kafka之ReplicaManager(1)

    基于Kafka 0.9.0版 ReplicaManager需要做什么 Replicated Logs Kafka的partition可以看成是一个replicated log, 每个replica就是 ...

  4. Java学习第三篇:类的三大特征,抽象类,接口,final关键字

    一.类的三大特征 1.封装性 (1).什么是封装 封装就是把抽象出的数据和对数据的操作封装在一起, 数据被保护在内部, 程序的其他部分只有通过被授权的操作(成员方法), 才能对数据进行操作. (2). ...

  5. jquery层居中,点击小图查看大图,弹出层居中代码

    1.层居中 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...

  6. Exceptionin thread "main" java.lang.UnsatisfiedLinkError:org.apache.hadoop.util.NativeCrc32.nativeComputeChunkedSumsByteArray(II[BI[BIILjav

    在eclipse上运行hadoop报错:Exceptionin thread "main" java.lang.UnsatisfiedLinkError:org.apache.ha ...

  7. Mac 下 docker安装

    http://www.th7.cn/system/mac/201405/56653.shtml Mac 下 docker安装 以及 处理错误Cannot connect to the Docker d ...

  8. P1011 传纸条//dp优化改进状态表示

    P1011 传纸条 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 NOIP2008复赛提高组第三题 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不 ...

  9. lintcode 中等题: Implement Trie

    题目 Implement Trie Implement a trie with insert, search, and startsWith methods. 样例   注意 You may assu ...

  10. IOS 开发中判断字符串是否为空字符的方法

    NSUInteger是无符号的整型, NSInteger是有符号的整型,在表视图应用中常见 NSUInteger row= [indexPath row];因为这是显示tableViewCell有多少 ...