题意:

平面上有n个点,现在要把它们全部连通起来。现在有q个套餐,如果购买了第i个套餐,则这个套餐中的点全部连通起来。也可以自己单独地建一条边,费用为两点欧几里得距离的平方。求使所有点连通的最小费用。

分析:

很明显,如果没有这些套餐的话,就是一个裸的MST。

可以枚举套餐的组合情况,然后把套餐中的边的权值置为0,再求MST。

在求MST的过程中,并不需要把所有的边都加进来。只要把原图的MST的那些边和套餐中的边加进来即可。

因为,对于不在原图的MST的边,购买套餐以后,按照权值排序,排在它之前的边不会减少,反而会因为购买套餐而在前面多出来一些权值为0的边。所以原图中被“淘汰”的边,在购买套餐后也一定会被“淘汰”。

 #include <cstdio>
#include <vector>
#include <algorithm>
using namespace std; const int maxn = + ;
const int maxq = ;
int n;
int x[maxn], y[maxn], cost[maxq];
vector<int> subn[maxq]; int pa[maxn];
int findset(int x) { return x == pa[x] ? x : pa[x] = findset(pa[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, 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 = findset(e[i].u), v = findset(e[i].v);
if(u != v)
{
pa[u] = v;
ans += e[i].d;
used.push_back(e[i]);
if(--cnt == ) break;
}
}
return ans;
} int main()
{
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--)
{
int q;
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-); //代码中节点的编号是从0开始的
}
}
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 = ; j < i; ++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) pa[i] = i;
sort(e.begin(), e.end()); int ans = MST(n, e, need);
for(int S = ; S < (<<q); ++S)
{//枚举所有套餐的组合情况
for(int i = ; i < n; ++i) pa[i] = i;
int cnt = n, c = ;
for(int i = ; i < q; ++i) if(S & (<<i))
{
c += cost[i];
for(int j = ; j < subn[i].size(); ++j)
{
int u = findset(subn[i][j]), v = findset(subn[i][]);
if(u != v) { --cnt; pa[u] = v; }
}
}
vector<Edge> hehe; //这里只是为了调用函数,所以弄了一个无关紧要的参数
ans = min(ans, c + MST(cnt, need, hehe));
} printf("%d\n", ans);
if(T) printf("\n");
} return ;
}

代码君

UVa 1151 (枚举 + MST) Buy or Build的更多相关文章

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

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

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

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

  3. POJ(2784)Buy or Build

    Buy or Build Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 1369   Accepted: 542 Descr ...

  4. Buy or Build (poj 2784 最小生成树)

    Buy or Build Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 1348   Accepted: 533 Descr ...

  5. 【uva 1151】Buy or Build(图论--最小生成树+二进制枚举状态)

    题意:平面上有N个点(1≤N≤1000),若要新建边,费用是2点的欧几里德距离的平方.另外还有Q个套餐,每个套餐里的点互相联通,总费用为Ci.问让所有N个点连通的最小费用.(2组数据的输出之间要求有换 ...

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

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

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

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

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

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

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

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

随机推荐

  1. Servlet实现web站点文件下载功能示例

    前段时间事情比较多,导致二月份没有记录自己的学习情况.最近接触了servlet,参考韩老师的教程自己写了一个web站点文件下载的小项目,该项目中还加入了简单的反盗链技术. 1.首先创建一个Shared ...

  2. RDD操作

    RDD操作 1.对一个数据为{1,2,3,3}的RDD进行基本的RDD转化操作 函数名 目的 示例 结果 map() 函数应用于RDD中的每个元素 rdd.map(x=>x+1) {2,3,4, ...

  3. Linux ps同时查找多个进程

    1.显示当前所有进程 SDCxM-SDCAM-root-root> ps aux USER       PID %CPU %MEM    VSZ   RSS TTY      STAT STAR ...

  4. sirius的python学习笔记(1)

    1.可以通过try...except语句来简单的判断字符串是否为整数值,如例程 x = raw_input('>') try: print int(x) except ValueError: r ...

  5. Linux学习系列之Linux入门(一)linux安装与入门

    第一篇:安装并配置Linux开发环境 一.安装linux: 主要安装Linux的发行版,到目前为之,主要的发行版有: 比较常用的是Ubuntu.redhat和centOS,主要的安装方法详细: Ubu ...

  6. win 7 64位如何安装erdas 9.2

    最主要的就是crack包必须包含这三个文件:erdas.exe、license.dat和lmgrd.exe 将这三个文件都复制到C盘安装目录下bin中,其余安装同win 7 32位系统

  7. oracle 将科学计数法数据转换为非科学计数法数据

    oracle 自定义函数: CREATE OR REPLACE FUNCTION ConvertNumeric(rawData VARCHAR2) --用于返回转换科学计算法dhx RETURN VA ...

  8. fineui框架

    http://fineui.com/demo/#/demo/layout/fit.aspx 虽然比较丑陋,但功能实用 此框架比较简单, 框架的作用你懂的,重点是要有帮助文档, 进阶型的容易上手的帮助文 ...

  9. 【学习总结】IOS程序运行过程 、UIWindow 、controller 、 UIView 创建过程的总结

    程序启动开始到view显示: 程序启动首先会执行main函数 - > UIApplicationMain函数: 程序启动 (加载框架,info文件,资源等) 执行Main函数 初始化UIAppl ...

  10. shell 实现word count

    awk '{arr[$2]+=$1}END{for (i in arr) print i,arr[i]}' sort_all.txt | sort -k2nr -g