UVA 1151 Buy or Build (最小生成树)
先求出原图的最小生成树,然后枚举买哪些套餐,把一个套餐内的点相互之间边权为0,直接用并查集缩点。正确性是基于一个贪心,
在做Kruskal算法是,对于没有进入最小生成树的边,排序在它前面的边不会减少。
边比较多,用prim求最小生成树,效果比Kruskal好,枚举套餐的时候在用Kruskal。
prim和dijkstra的区别在于点距离的定义。
#include<bits/stdc++.h>
using namespace std;
const int maxn = ;
int n,q; int C[];
vector<int> Buy[];
#define PB push_back int x[maxn],y[maxn];
#define squ(x) ((x)*(x)) int dist(int a,int b) { return squ(x[a]-x[b])+squ(y[a]-y[b]); } struct Edge
{
int u,v,w;
Edge(){}
Edge(int u,int v,int w):u(u),v(v),w(w){}
bool operator < (const Edge& x) const {
return w > x.w;
}
}edges[maxn]; bool EdgeLess(const Edge &x,const Edge &y) { return x.w < y.w; } int ecnt; int d[maxn];
bool done[maxn];
const int INF = 0x3f3f3f3f; int Prim()
{
fill(d,d+n,INF);
fill(done,done+n,);
ecnt = ;
priority_queue<Edge> q;
q.push(Edge(-,,)); // dummy edge
int tot = d[] = ;
while(q.size()){
Edge x = q.top(); q.pop();
if(done[x.v]) continue;
edges[ecnt++] = x;
tot += x.w;
done[x.v] = true;
for(int i = ; i < n; i++){
if(done[i]) continue;
int cost = dist(x.v,i);
if(d[i]>cost){
d[i] = cost;
q.push(Edge(x.v,i,cost));
}
}
}
return tot;
} int pa[maxn];
int Find(int x) { return x==pa[x]?x:pa[x]=Find(pa[x]); }
void Union(int a,int b,int &cnt)
{
int s1 = Find(a),s2 = Find(b);
if(s1 != s2){
pa[s1] = s2; cnt--;
}
} int Kruskal(int cnt)
{
if(!cnt) return ;
int ans = ;
for(int i = ; i < ecnt; i++){
Edge &e = edges[i];
int s1 = Find(e.u), s2 = Find(e.v);
if(s1 != s2) { ans += e.w; pa[s1] = s2; cnt--; if(!cnt) return ans; } }
return ans;
} int main()
{
//freopen("in.txt","r",stdin);
int T; scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&q);
for(int i = ; i < q; i++){
int t; scanf("%d%d",&t,C+i);
Buy[i].clear();
while(t--) {
int c; scanf("%d",&c);
Buy[i].PB(c-);
}
}
for(int i = ; i < n; i++){
scanf("%d%d",x+i,y+i);
}
int ans = Prim();
sort(edges+,edges+ecnt,EdgeLess); for(int mask = ,M = <<q; mask < M; mask++){
for(int i = ; i < n; i++) pa[i] = i;
int tot = ,cnt = n-; for(int i = ; i < q; i++){
if(mask&<<i){
tot += C[i];
for(int j = ; j < Buy[i].size(); j++) {
Union(Buy[i][],Buy[i][j],cnt);
}
}
} tot += Kruskal(cnt);
ans = min(ans,tot);
}
printf("%d\n",ans);
if(T) putchar('\n');
}
return ;
}
UVA 1151 Buy or Build (最小生成树)的更多相关文章
- UVa 1151 - Buy or Build(最小生成树)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- UVA 1151 Buy or Build MST(最小生成树)
题意: 在平面上有n个点,要让所有n个点都连通,所以你要构造一些边来连通他们,连通的费用等于两个端点的欧几里得距离的平方.另外还有q个套餐,可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相 ...
- UVA 1151 Buy or Build (MST最小生成树,kruscal,变形)
题意: 要使n个点之间能够互通,要使两点直接互通需要耗费它们之间的欧几里得距离的平方大小的花费,这说明每两个点都可以使其互通.接着有q个套餐可以选,一旦选了这些套餐,他们所包含的点自动就连起来了,所需 ...
- uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)
最小生成树算法简单 只是增加了一些新的东西,对于需要最小生成树算法 和中 并检查使用的一系列 还有一些更深入的了解. 方法的一些复杂问题 #include<cstdio> #include ...
- UVa 1151 Buy or Build (最小生成树+二进制法暴力求解)
题意:给定n个点,你的任务是让它们都连通.你可以新建一些边,费用等于两点距离的平方(当然越小越好),另外还有几种“套餐”,可以购买,你购买的话,那么有些边就可以连接起来, 每个“套餐”,也是要花费的, ...
- UVa 1151 Buy or Build【最小生成树】
题意:给出n个点的坐标,现在需要让这n个点连通,可以直接在点与点之间连边,花费为两点之间欧几里得距离的平方,也可以选购套餐,套餐中所含的点是相互连通的 问最少的花费 首先想kruskal算法中,被加入 ...
- UVA - 1151 Buy or Build (买还是建)(并查集+二进制枚举子集)
题意:平面上有n个点(1<=n<=1000),你的任务是让所有n个点连通.可以新建边,费用等于两端点欧几里德距离的平方.也可以购买套餐(套餐中的点全部连通).问最小费用. 分析: 1.先将 ...
- UVA 1151 买还是建(最小生成树)
买还是建 紫书P358 [题目链接]买还是建 [题目类型]最小生成树 &题解: 这题真的心累,看了3天,最后照着码还是wa,先放lrj代码,以后再看吧 &代码: // UVa1151 ...
- UVA 1151二进制枚举子集 + 最小生成树
题意:平面上有n个点(1<=N<=1000),你的任务是让所有n个点连通,为此, 你可以新建一些边,费用等于两个端点的欧几里得距离的平方.另外还有q(0<=q<=8)个套餐(数 ...
随机推荐
- intellj idea 使用
1. 导入包快捷 Alt + Enter 2. 查看方法注释,点击进入源码即可,若想和eclipse一样鼠标停留即可出现注释提示,开启方法为: Preferences->Editor->G ...
- OGNL和类型转换
转载 JavaWeb -- Struts 数据传输:OGNL和类型转换 1. 数据传输:OGNL和类型转换 OGNL和struts2 OGNL:Object-Graph Navigation Lang ...
- UVa 11520 Fill the Square (水题,暴力)
题意:给n*n的格子里填上A-Z的字符,保证相邻字符不同,并且字典序最小. 析:直接从第一个格子开始暴力即可,每次判断上下左是不是相同即可. 代码如下: #pragma comment(linker, ...
- UVA - 11987 Almost Union-Find 并查集的删除
Almost Union-Find I hope you know the beautiful Union-Find structure. In this problem, you're to imp ...
- 如何实现Ant design表单组件封装?
目标:自己实现一个antd表单组件 先看下Ant Design官网上给出的表单组件用法: import React, { Component } from 'react' import { Form, ...
- AtCoder Beginner Contest 087 D People on a Line(DFS)
题意 给出n个点,m组关系L,R,D,L在R的左边距离D,判断是否存在n个人的位置满足m组关系 分析 Consider the following directed graph G: There ar ...
- POJ3734【状压枚举】
题意: 给你两个01矩阵,去掉矩阵B的某些行和某些列,问处理后的矩阵B能否变成矩阵A: 思路: 数据较小,状压枚举B矩阵列的数量=A矩阵列的数量时的状态,然后搞定了列,贪心判断B矩阵的行就好了: #i ...
- 洛谷 P1712 [NOI2016]区间(线段树)
传送门 考虑将所有的区间按长度排序 考虑怎么判断点被多少区间覆盖,这个可以离散化之后用一棵权值线段树来搞 然后维护两个指针$l,r$,当被覆盖次数最多的点的覆盖次数小于$m$时不断右移$r$,在覆盖次 ...
- ERROR: Could not connect to lockdownd, error code -19 -20
执行命令行 brew install libimobiledevice --HEAD
- base64模块
********base64模块******** Base64是一种用64个字符来表示任意二进制数据的方法. 用记事本打开exe.jpg.pdf这些文件时,我们都会看到一大堆乱码,因为二进制文件包含很 ...