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

首先想kruskal算法中,被加入的边已经是最优的了,所以当选择完套餐后,之前被丢弃的边也不会再进入最小生成树

然后就可以先求一次原图的最小生成树,保存下进入最小生成树的n-1条边

再枚举选择的套餐的情况,再求最小生成树,这里用的二进制法枚举 最后维护一个最小值就可以了

思路虽然看懂了,可是代码根本就写不出来,看着标程写的,最后还是改了那么久-- sad----------

 #include<iostream>
#include<cstdio>
#include<cstring>
#include <cmath>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
using namespace std; #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i) typedef long long LL;
const int INF = (<<)-;
const int mod=;
const int maxn=;
const int maxq=; int n;
int x[maxn],y[maxn],cost[maxn];
vector<int> subn[maxn]; int p[maxn];
int find(int x) {return p[x]!=x? p[x]=find(p[x]):x;} struct edge{
int u,v,d;
edge(int u,int v,int d):u(u),v(v),d(d) {}
bool operator <(const edge& rhs) const{
return d<rhs.d;}
}; int mst(int cnt,const vector<edge>& e,vector<edge>& used){
if(cnt==) return ;
int m=e.size();
int ans=;
used.clear();
for(int i=;i<m;i++){
int u=find(e[i].u),v=find(e[i].v);
int d=e[i].d;
if(u!=v){
p[u]=v;
ans+=d;
used.push_back(e[i]);
if(--cnt==) break;
}
}
return ans;
} int main(){
// freopen("in.txt","r",stdin);
// freopen("outttttttt.txt","w",stdout);
int T,q;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&q);
for(int i=;i<q;i++){
int cnt;
scanf("%d %d",&cnt,&cost[i]);
subn[i].clear();
while(cnt--){
int u;
scanf("%d",&u);
subn[i].push_back(u-);
}
} for(int i=;i<n;i++) scanf("%d %d",&x[i],&y[i]); vector<edge> e,need; for(int i=;i<n;i++)
for(int j=i+;j<n;j++){
int c=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
e.push_back(edge(i,j,c));
} for(int i=;i<n;i++) p[i]=i;
sort(e.begin(),e.end()); int ans=mst(n,e,need); for(int mask=;mask<(<<q);mask++){ for(int i=;i<n;i++) p[i]=i;
int cnt=n,c=; for(int i=;i<q;i++) if(mask & (<<i)){
c+=cost[i];
for(int j=;j<subn[i].size();j++){
int u=find(subn[i][j]),v=find(subn[i][]);
if(u!=v){p[u]=v;cnt--;}
}
}
vector<edge> dummy;
ans=min(ans,c+mst(cnt,need,dummy));
}
printf("%d\n",ans);
if(T) printf("\n");
}
return ;
}

UVa 1151 Buy or Build【最小生成树】的更多相关文章

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

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

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

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

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

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

  4. UVA 1151 Buy or Build (MST最小生成树,kruscal,变形)

    题意: 要使n个点之间能够互通,要使两点直接互通需要耗费它们之间的欧几里得距离的平方大小的花费,这说明每两个点都可以使其互通.接着有q个套餐可以选,一旦选了这些套餐,他们所包含的点自动就连起来了,所需 ...

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

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

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

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

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

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

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

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

  9. UVA 1151二进制枚举子集 + 最小生成树

    题意:平面上有n个点(1<=N<=1000),你的任务是让所有n个点连通,为此, 你可以新建一些边,费用等于两个端点的欧几里得距离的平方.另外还有q(0<=q<=8)个套餐(数 ...

随机推荐

  1. 2.windows下安装git

    转自:https://blog.csdn.net/lvkelly/article/details/54666868

  2. java布局管理

    FlowLayout :组件在一行中按加入的先后顺序从左至右水平排列,排满后折行,每行中的组件都居中排列.BorderLayout:把容器空间划分为北.南.西.东.中五个区,每加入一个组件都应说明把这 ...

  3. Page Layout里的javascript (jquery)不执行

    在page layout 中通过 _spBodyOnLoadFunctionNames.push("js 方法名") 的方式实现. 但切记,代码要放到 PlaceHolderMai ...

  4. Windows服务的创建,安装,卸载

    我公司项目的产线系统要与WMS物流系统做借口对接,需要我创建一个windows服务的项目,里面含有7个服务 创建Windows服务: 1.如图:点击 windows->经典桌面->wind ...

  5. js小结2

    1.includes和contains 对于字符串,数组来说,判断包含是includes,对classList是contains 2.编辑span内容,enter提交(如何避免keydown之后换行: ...

  6. 51nod 1572 宝岛地图 (预处理四个方向的最大步数优化时间,时间复杂度O(n*m+k))

    题目: 这题如果没有时间限制的话暴力可以解,暴力的话时间复杂度大概是O(k*n),1s的话非常悬. 所以我们需要换个思路,我们对每个点预处理四个方向最多能走的步数,这个预处理时间复杂度是O(n*m). ...

  7. 《剑指offer》二叉搜索树与双向链表

    一.题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向 二.输入描述 输入一棵二叉搜索树 三.输出描述 将该二叉搜索树转换成一个 ...

  8. omi-mp-create源码加注

    omi-mp-create是dntzhang写的小程序框架,主要功能是实现全局状态自动更新和页面间通信,传送门. 代码虽然简单但是注释不多读起来还是需要一点时间理解,因此在上面加入了个人理解的注释方便 ...

  9. BZOJ 2938 [POI2000]病毒 (剪枝/A*迭代搜索)

    LOJ BZOJ 题目大意:给你一些模式串,问是否存在一个无限长的文本串,不包含任何一个给定的模式串 并没有想到去模拟合法的文本串在模式串的Trie图上匹配的过程..我好菜啊 如果一个字符串合法,那么 ...

  10. CentOS7 部署SVN服务器

    服务器端:svnserver 安装主要步骤 yum install subversion rpm -ql subversion mkdir /application/svndata mkdir /ap ...