https://vjudge.net/problem/UVA-1151

题意:

平面上有n个点,你的任务是让所有n个点连通。为此,你可以新建一些边,费用等于两个端点的距离平方和。另外还有q个套餐可以购买,如果你购买了第i个套餐,该套餐中的所有结点都变得相互连通,第i个套餐的花费为Ci。

思路:

这道题比较容易超时。可能需要用到并查集的路径压缩,我下面的代码就是用了路径压缩,不然要超时。也是看了别人的代码才知道还有这种省时间的做法。

先介绍一下路径压缩吧:

如果并查集像一字长蛇这样排列的话,寻找起来就比较费时间,但如果像图2一样的话,一下子就可以找到根了。压缩的方法也是挺简单的。

     int r = x;
while (r != p[r]) r = p[r];
int i = x, j;
while (p[i] != r)
{
j = p[i];
p[i] = r;
i = j;
}

题目的做法就像紫书上说的那样,先不考虑套餐算一遍,然后枚举套餐的方法,这里的话二进制枚举法非常方便。

 #include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std; const int maxn = + ; int n, m, q, cnt;
int p[maxn];
vector<int> g[]; //方案集合
int c[]; //方案价格 //边
struct node
{
int u;
int v;
int dist;
}edge[maxn*maxn]; //点
struct node2
{
int x, y;
}a[maxn]; int find(int x)
{
//return p[x] == x ? x : find(p[x]); 用这个会超时
//路径压缩
int r = x;
while (r != p[r]) r = p[r];
int i = x, j;
while (p[i] != r)
{
j = p[i];
p[i] = r;
i = j;
}
return r;
} bool cmp(node a, node b)
{
return a.dist < b.dist;
} //计算距离平方和
int cacl_dist(node2 a, node2 b)
{
return (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y);
} void init()
{
for (int k = ; k <= n; k++) p[k] = k;
} int Kruskal()
{
int num = ;
int ans = ;
for (int i = ; i < cnt ; i++)
{
int x = find(edge[i].u);
int y = find(edge[i].v);
if (x != y)
{
p[x] = y;
ans += edge[i].dist;
num++;
}
if (num == n - ) return ans;
}
return ans;
} void solve()
{
init();
int ans = Kruskal();
//二进制枚举方案
for (int i = ; i < ( << q); i++)
{
init();
int cost = ;
for (int j = ; j < q; j++)
{
if (i & ( << j))
{
cost += c[j];
int x = find(g[j][]);
for (int k = ; k < g[j].size(); k++)
{
int y = find(g[j][k]);
if (x != y)
p[y] = x;
}
}
}
ans = min(cost + Kruskal(), ans);
}
printf("%d\n", ans);
} int main()
{
//freopen("D:\\txt.txt", "r", stdin);
int T, t, s, kase=;
scanf("%d", &T);
while (T--)
{
if (++kase > ) printf("\n");
scanf("%d%d", &n, &q); //存储方案
for (int i = ; i < q; i++)
{
g[i].clear();
scanf("%d", &t);
scanf("%d", &c[i]);
for (int j = ; j < t; j++)
{
scanf("%d", &s);
g[i].push_back(s);
}
} for (int i = ; i <= n; i++)
scanf("%d%d", &a[i].x, &a[i].y); //存储边
cnt = ;
for (int i = ; i <= n;i++)
for (int j = i + ; j <= n; j++)
{
edge[cnt].u = i;
edge[cnt].v = j;
edge[cnt].dist = cacl_dist(a[i], a[j]);
cnt++;
}
sort(edge, edge + cnt, cmp);
solve();
}
return ;
}

UVa 1151 买还是建的更多相关文章

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

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

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

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

  3. 洛谷 题解 UVA1151 【买还是建 Buy or Build】

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

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

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

  5. UVA 1151

    /* 题意:有n个点,现在需要联通所有,有q种套餐可以选择, 当然套餐之外也可以自己添加边,意为达到最短距离. 题意很明显,不知道需要使用哪一种套餐, 那么需要枚举每一种套餐的情况. 然后再进行对比. ...

  6. uva 1151(最小生成树,枚举子集)

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

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

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

  8. UVa 1151 (枚举 + MST) Buy or Build

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

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

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

随机推荐

  1. Prometheus+Grafana+Altermanager搭建监控系统

    基本概念 Prometheus 时间序列化数据库,我的理解就是将数据打上标签,以时间维度存储.后面有机会在深入研究. Prometheus架构如下: Grafana Prometheus中存储的数据, ...

  2. abap关键字

    1:abap将提升的关键字快捷输入 按tab键,提示的关键字将会自动输入. 2:shift tab 用于对其格式 3:ctrl+d 将改行复制到下一行.

  3. [py]django表单不清空实现的2种方法

    参考 参考: django实现内容不清空2种方法 django form的作用 1.生成html标签 2.验证输入内容 form生成表单 zhuji/forms.py - 实例化表单 - 定制form ...

  4. win10 java环境变量的正确配置

    变量名:[JAVA_HOME]变量值:[D:\Program Files\Java\jdk1.8.0_92][jdk安装路径]变量名:[Path]变量值:[;%JAVA_HOME%\bin;%JAVA ...

  5. 4.keras实现-->生成式深度学习之DeepDream

    DeepDream是一种艺术性的图像修改技术,它用到了卷积神经网络学到的表示,DeepDream由Google于2015年发布.这个算法与卷积神经网络过滤器可视化技术几乎相同,都是反向运行一个卷积神经 ...

  6. Bus,Exclusive access,memory attribute

    指令LDREX,STREX是在armv6中新加的指令,配合AMBA3--AXI中的lock[1:0]信号. 在Atomic Access一节中是这么规定的:ARLOCK[1:0]/AWLOCK[1:0 ...

  7. NOSQL学习之二:MongoDB

    MongoDB是一个高性能,开源,无模式的文档型数据库,它在许多场景下可用于替代传统的关系型数据库或键/值存储方式,是当前NoSQL数据库中比较热门的一种. MongoDB使用C++开发.不支持SQL ...

  8. RPC和RabbitMQ

    在单台机器或者单个进程中,如果要调用某个函数,只需要通过函数指针,传入相关参数,即可调用成功并获得结果.但如果是在分布式系统中,某个进程想要调用远程机器上的其它进程提供的方法(服务),就需要采用RPC ...

  9. JProfiler8 远程监控tomcat配置过程

    1. 阅读人群 1.熟悉liunx服务器,起码知道liunx常见的命令 2.熟悉tomcat容器,起码知道怎么tomcat的启动以及停止 3.熟悉java编程语言,JProfiler8是专门监控jav ...

  10. 怎样将一个整数转化成字符串数,并且不用函数itoa

    #include<iostream> using namespace std; int main() { , j = , i = ; ], str[]; while (num) { tem ...