UVA 1151 Buy or Build (MST最小生成树,kruscal,变形)
题意:
要使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,变形)的更多相关文章
- UVA 1151 Buy or Build MST(最小生成树)
题意: 在平面上有n个点,要让所有n个点都连通,所以你要构造一些边来连通他们,连通的费用等于两个端点的欧几里得距离的平方.另外还有q个套餐,可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相 ...
- UVa 1151 - Buy or Build(最小生成树)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- UVA 1151 Buy or Build (最小生成树)
先求出原图的最小生成树,然后枚举买哪些套餐,把一个套餐内的点相互之间边权为0,直接用并查集缩点.正确性是基于一个贪心, 在做Kruskal算法是,对于没有进入最小生成树的边,排序在它前面的边不会减少. ...
- UVa 1151 Buy or Build【最小生成树】
题意:给出n个点的坐标,现在需要让这n个点连通,可以直接在点与点之间连边,花费为两点之间欧几里得距离的平方,也可以选购套餐,套餐中所含的点是相互连通的 问最少的花费 首先想kruskal算法中,被加入 ...
- UVa 1151 Buy or Build (最小生成树+二进制法暴力求解)
题意:给定n个点,你的任务是让它们都连通.你可以新建一些边,费用等于两点距离的平方(当然越小越好),另外还有几种“套餐”,可以购买,你购买的话,那么有些边就可以连接起来, 每个“套餐”,也是要花费的, ...
- uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)
最小生成树算法简单 只是增加了一些新的东西,对于需要最小生成树算法 和中 并检查使用的一系列 还有一些更深入的了解. 方法的一些复杂问题 #include<cstdio> #include ...
- UVA - 1151 Buy or Build (买还是建)(并查集+二进制枚举子集)
题意:平面上有n个点(1<=n<=1000),你的任务是让所有n个点连通.可以新建边,费用等于两端点欧几里德距离的平方.也可以购买套餐(套餐中的点全部连通).问最小费用. 分析: 1.先将 ...
- 紫书 例题 11-3 UVa 1151 (有边集的最小生成树+二进制枚举子集)
标题指的边集是说这道题的套餐, 是由几条边构成的. 思路是先做一遍最小生成树排除边, 因为如果第一次做没有加入的边, 到后来新加入了很多权值为0的边,这些边肯定排在最前面,然后这条边的前面的那些边肯定 ...
- UVA 1151 买还是建(最小生成树)
买还是建 紫书P358 [题目链接]买还是建 [题目类型]最小生成树 &题解: 这题真的心累,看了3天,最后照着码还是wa,先放lrj代码,以后再看吧 &代码: // UVa1151 ...
随机推荐
- uoj 67 新年的毒瘤 割点
题目链接: 题目 #67. 新年的毒瘤 问题描述 辞旧迎新之际,喜羊羊正在打理羊村的绿化带,然后他发现了一棵长着毒瘤的树. 这个长着毒瘤的树可以用 nn 个结点 mm 条无向边的无向图表示.这个图中有 ...
- 【BZOJ】【1272】【BeiJingWC2008】Gate of Babylon
组合数学+容斥原理 Orz zyf-zyf 多重集组合数0.0还带个数限制? ——> <组合数学>第6章 6.2带重复的组合 组合数还要模P 0.0? ——> Lucas ...
- C# 生成MD5编码方法(不同位数)
/// <summary> /// </summary> /// <param name="strSource"& ...
- Linux下配置安装PHP环境
参考别人的做法,遇到问题上网查,下面就是安装步骤. 一.安装Apache2.2.221.到官网下载 http://httpd.apache.org/download.cgi 2.解压 t ...
- 01-03-03【Nhibernate (版本3.3.1.4000) 出入江湖】cascade的测试
相关文章: http://www.cnblogs.com/amboyna/archive/2008/02/18/1072260.html注意上面是hibernate,不是Nhibernate,这解释是 ...
- Volatile 说明
Java™ 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量.这两种机制的提出都是为了实现代码线程的安全性.其中 Volatile 变量的同步性较差(但有时它更简单并且开销更低) ...
- StringTokenizer用法
import java.util.StringTokenizer; public class StringTokenizerTest { public static void main(String[ ...
- mybatis 插入日期类型精确到秒的有关问题
mybatis 插入日期类型精确到秒的问题 Mybatis 插入 数据库是为了防止插入空时报错, Mybatis 提供了一套机制,只要给定插入的字段的类型,如果为空,则它会自动处理为相应类型的默认值: ...
- kindeditor.net应用
1.网址:http://kindeditor.net/docs/usage.html
- http://www.aboutyun.com/thread-6551-1-1.html
http://www.aboutyun.com/thread-6551-1-1.html