题意:平面上有n个点(1<=N<=1000),你的任务是让所有n个点连通,为此,你可以新建一些边,费用等于两个端点的欧几里得距离的平方。另外还有q(0<=q<=8)个套餐,可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相互连通,第i个套餐的花费为ci。

kruskal:

先求一次原图的最小生成树,得到n-1条边,然后每次枚举完套餐后只考虑套餐中的边和这n-1条边,则枚举套餐之后再求最小生成树。

key:

kruskal算法中,那些两端已经属于同一个连通分量的边不会再加到生成树里面。

那么买了套餐后,相当于一些边的权变为0,而对于不在套餐中的每条边e,排序在e之前的边一个也没少,反而可能多了一些权值为0的边。

所以在 原图kruskal时被扔掉的边,在购买套餐后的Kruskal中也一样会被扔掉。

#include <cstdio>
#include <iostream>
#include <sstream>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
#define ll int
#define _cle(m, a) memset(m, a, sizeof(m))
#define repu(i, a, b) for(int i = a; i < b; i++)
#define repd(i, a, b) for(int i = b; i >= a; i--)
#define sfi(n) scanf("%d", &n)
#define pfi(n) printf("%d\n", n)
#define sfi2(n, m) scanf("%d%d", &n, &m)
#define sfd2(n, m) scanf("%lf%lf", &n, &m)
#define pfi2(n, m) printf("%d %d\n", n, m)
#define pfi3(a, b, c) printf("%d %d %d\n", a, b, c)
const int INF = 0x3f3f3f3f; #define maxn 1010
#define maxm 1500010
ll w[maxm];
int m;
int r[maxm];
int u[maxm], v[maxm], p[maxn];
ll xx[maxn], yy[maxn];
int kb[maxn];
vector<int> f[];
int n, q, num[];
int c[];
int cmp(const int i, const int j)
{
return w[i] < w[j];
}
int Find(int x)
{
return p[x] == x ? x : p[x] = Find(p[x]);
}
ll Kruskal1()
{
ll ans = ;
int len = ;
repu(i, , m)
{
int e = r[i];
int x = Find(u[e]);
int y = Find(v[e]);
if(x != y)
{
kb[len++] = e;
ans += w[e];
p[x] = y;
}
}
return ans;
} ll Kruskal2()
{
ll ans = ;
int len = ;
int t = n - ;
repu(i, , n - )
{
int e = kb[i];
int x = Find(u[e]);
int y = Find(v[e]);
if(x != y)
{
ans += w[e];
p[x] = y;
}
}
return ans;
} int main()
{
int T;
sfi(T);
while(T--)
{
sfi2(n, q);
m = ;
repu(i, , q)
{
int a;
sfi2(num[i], c[i]);
f[i].clear();
repu(j, , num[i]) sfi(a), f[i].push_back(a);
}
repu(i, , n + ) scanf("%d%d", &xx[i], &yy[i]);
repu(i, , n + )
repu(j, + i, n + )
{
w[m] = (xx[i] - xx[j]) * (xx[i] - xx[j]) + (yy[i] - yy[j]) * (yy[i] - yy[j]);
u[m] = i;
v[m] = j;
//printf("%d %d %d %lf\n", m, i, j, w[m]);
m++; } repu(i, , n + ) p[i] = i;
repu(i, , m) r[i] = i;
sort(r, r + m, cmp);
ll minn = Kruskal1();
sort(kb, kb + n - , cmp);
//printf("%lld\n", minn);
int lim = <<q;
ll cc;
repu(i, , lim)
{
cc = ;
repu(j, , n + ) p[j] = j;
repu(j, , q) if((<<j) & i)
if(num[j])
{
cc += c[j];
int x = Find(f[j][]);
repu(k, , num[j])
{
int y = Find(f[j][k]);
if(x != y) p[y] = x;
}
//printf("%d %d\n", i, j);
}
minn = min(minn, cc + Kruskal2());
//printf("%lld\n", minn);
}
printf("%d\n", minn);
if(T) puts("");
}
return ;
}

uva 1151(最小生成树,枚举子集)的更多相关文章

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

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

  2. uva 1151最小生成树

    先求一次最小生成树,可以排除n*(n*1)/2-(n-1)条边,每次利用二进制法枚举套餐的选择,套餐中的点直接处理,如果两个套餐有公共点直接合并,他们一定连通,然后枚举第一步最小生成树得到的n-1条边 ...

  3. uva 11088 暴力枚举子集/状压dp

    https://vjudge.net/problem/UVA-11088 对于每一种子集的情况暴力枚举最后一个三人小组取最大的一种情况即可,我提前把三个人的子集情况给筛出来了. 即 f[S]=MAX{ ...

  4. Buy or Build UVA - 1151 Kruskal+枚举

    题意: 大概意思是有 n 个点,现在有 q 个方案 ,第 i 个方案耗费为 ci ,使 Ni 个点联通 ,当然也可以直接使两点联通 ,现求最小生成树的代价. 两点直接联通的代价是欧几里得距离的平方: ...

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

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

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

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

  7. UVa 11825 - Hackers' Crackdown DP, 枚举子集substa = (substa - 1)&sta 难度: 2

    题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  8. UVA 1508 - Equipment 状态压缩 枚举子集 dfs

    UVA 1508 - Equipment 状态压缩 枚举子集 dfs ACM 题目地址:option=com_onlinejudge&Itemid=8&category=457& ...

  9. UVA 11825 - Hackers&#39; Crackdown 状态压缩 dp 枚举子集

    UVA 11825 - Hackers' Crackdown 状态压缩 dp 枚举子集 ACM 题目地址:option=com_onlinejudge&Itemid=8&page=sh ...

  10. UVa 11025 The broken pedometer【枚举子集】

    题意:给出一个矩阵,这个矩阵由n个数的二进制表示,p表示用p位二进制来表示的一个数 问最少用多少列就能将这n个数区分开 枚举子集,然后统计每一种子集用了多少列,维护一个最小值 b[i]==1代表的是选 ...

随机推荐

  1. DOM based XSS Prevention Cheat Sheet(DOM Based XSS防御检查单)

    本文为翻译版本,原文请查看 https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet 介绍 谈到XSS攻击,有三种公认的 ...

  2. [Android Tips] 9. framework notification layout font size

    android 4.4 framework notification layout 相关字体大小 * title: notification_title_text_size: 18dp * conte ...

  3. 【转修正】sql server行版本控制的隔离级别

    在SQL Server标准的已提交读(READ COMMITTED)隔离级别下,一个读操作会和一个写操作相互阻塞.未提交读(READ UNCOMMITTED)虽然不会有这种阻塞,但是读操作可能会读到脏 ...

  4. python IDE

    提供给开发者 10 款最好的 Python IDE http://www.oschina.net/news/57468/best-python-ide-for-developers vim windo ...

  5. oauth协议

    微博 : 新浪 腾讯 OAuth 新浪微博   APP开发 步骤:1.注册新浪开发者账号 获取以下信息 client_id  123456  标示应用身份的  唯一的  有的也叫App Key sec ...

  6. SQL批量添加主键脚本

    --SQL批量添加主键脚本 --操作提示:运行此脚本前请记得备份您要操作的数据库 --实现功能:执行脚本后数据库中的所有数据表都会有一个主键 --添加规则1:主键名称为ID(可自己修改),数据类型为整 ...

  7. SQL2005中的事务与锁定(九)- 转载

    ------------------------------------------------------------------------ -- Author : HappyFlyStone - ...

  8. iOS中UIWebView与其中网页的javascript的交互

    首发:个人博客,更新&纠错&回复 1.本地语言调js的方式与android中的方式类似,也是向WebView控件发送要调用的js语句 2. 但js调本地语言,则不是像android那样 ...

  9. JAVA下的Thread.sleep方法一定要try

    try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } 不同于C#,JAVA里的Thre ...

  10. 用webdriver+phantomjs实现无浏览器的自动化过程

    环境准备 1. 安装python: 2. 安装pip: 3. 通过pip安装selenium: 4. 下载phantomJS的包并解压缩: 1. 若在Windows系统中,将下载的phantomjs文 ...