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. MVC前后台获取Action、Controller、ID名方法 以及 路由规则

    前后台获取Action.Controller.ID名方法 前台页面:ViewContext.RouteData.Values["Action"].ToString();//获取Ac ...

  2. keras之save & reload model

    import numpy as np np.random.seed(1337) # for reproducibility from keras.models import Sequential fr ...

  3. try except else

    try except 语句还有一个可选的else子句,如果使用这个子句,那么必须放在所有的except子句之后.这个子句将在try子句没有发生任何异常的时候执行.例如: for arg in sys. ...

  4. <A Decomposable Attention Model for Natural Language Inference>(自然语言推理)

    http://www.xue63.com/toutiaojy/20180327G0DXP000.html 本文提出一种简单的自然语言推理任务下的神经网络结构,利用注意力机制(Attention Mec ...

  5. yii2关联查询两组一对一

    public function getMember1(){        return $this->hasOne(Member::className(), ['wechat_id' => ...

  6. DIV内容垂直居中

    css垂直居中属性设置vertical-align: middle对div不起作用,例如: <!DOCTYPE html> <html lang="zh-CN"& ...

  7. C++ 简明教程

    C++是一种系统编程语言.用它的发明者, Bjarne Stroustrup的话来说,C++的设计目标是: 成为“更好的C语言” 支持数据的抽象与封装 支持面向对象编程 支持泛型编程 C++提供了对硬 ...

  8. LoadRunner 自动关联、手动关联的帖子

    https://www.guru99.com/correlation-in-loadrunner-ultimate-guide.html 这个网页里介绍了关联的概念,自动关联和手动关联的知识...

  9. Filter过滤器与Session会话跟踪技术

    Filter过滤器 适用场景 1.为web应用程序的新功能建立模型(可被添加到web应用程序中或者从web应用程序中删除而不需要重写基层应用程序代码)2.用户授权Filter:负责检查用户请求,根据请 ...

  10. linux基础命令---bzip2

    bzip2 使用Burrows-Wheeler块排序文本压缩算法,将文件进行压缩,压缩比率比一般算法高一些.bzip2要求命令行标志附带一个文件名列表.每个文件都被自己的压缩版本替换,名称为“orig ...