UVA1151
//感觉刘汝佳老师的思维真的太厉害了orz
/*摘录书上的一段话: 只需一个小小的优化即可降低时间复杂度:先求一次原图(不购买任何套餐)的最小生
成树,得到n-1条边,然后每次枚举完套餐后只考虑套餐中的边和这n-1条边,则枚举套餐之
后再求最小生成树时,图上的边已经寥寥无几。
为什么可以这样呢?首先回顾一下,在Kruskal算法中,哪些边不会进入最小生成树。答
案是:两端已经属于同一个连通分量的边。买了套餐以后,相当于一些边的权变为0,而对
于不在套餐中的每条边e,排序在e之前的边一个都没少,反而可能多了一些权值为0的边,
所以在原图Kruskal时被“扔掉”的边,在后面的Kruskal中也一样会被扔掉。*/
// UVa1151 Buy or Build
// Rujia Liu
#include<cstdio>
#include<cmath>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
+ ;
;
int n;
int x[maxn], y[maxn], cost[maxq];
vector<int> subn[maxq];
int pa[maxn];
int findset(int x) { return pa[x] != x ? pa[x] = findset(pa[x]) : 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;
}
};
// initialize pa and sort e before calling this method
// cnt is the current number of components
int MST(int cnt, const vector<Edge>& e, vector<Edge>& used) { //找出原图跑一边kruskal之后用过的边
) ;
int m = e.size();
;
used.clear();
; i < m; i++) {
int u = findset(e[i].u), v = findset(e[i].v);
int d = e[i].d;
if(u != v) {
pa[u] = v;
ans += d;
used.push_back(e[i]);
) break;
}
}
return ans;
}
int main() {
int T, q;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &q);
; 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-);
}
}
; i < n; i++) scanf("%d%d", &x[i], &y[i]);
vector<Edge> e, need;
; i < n; i++)
; j < n; 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));
}
; i < n; i++) pa[i] = i;
sort(e.begin(), e.end());
int ans = MST(n, e, need);
; mask < (<<q); mask++) { //枚举套餐,二进制法
// union cities in the same sub-network
; i < n; i++) pa[i] = i;
;
; i < q; i++) <<i)) {
c += cost[i];
; j < subn[i].size(); j++) {
]);
if(u != v) { pa[u] = v; cnt--; }
}
}
vector<Edge> dummy;
ans = min(ans, c + MST(cnt, need, dummy));
}
printf("%d\n", ans);
if(T) printf("\n");
}
;
}
UVA1151的更多相关文章
- UVa1151 Buy or Build
填坑(p.358) 以前天真的以为用prim把n-1条边求出来就可以 现在看来是我想多了 #include<cstdio> #include<cstring> #include ...
- 【最小生成树+子集枚举】Uva1151 Buy or Build
Description 平面上有n个点(1<=N<=1000),你的任务是让所有n个点连通,为此,你可以新建一些边,费用等于两个端点的欧几里得距离的平方. 另外还有q(0<=q< ...
- Buy or Build(UVa1151)
如果枚举每个套餐,并每次都求最小生成树,总时间复杂度会很高,因而需要先求一次原图的最小生成树,则枚举套餐之后需要考虑的边大大减少了. 具体见代码: #include<cstdio> #in ...
- 洛谷 题解 UVA1151 【买还是建 Buy or Build】
[题意] 平面上有\(n(n<=1000)\)个点,你的任务是让所有n个点联通.为此,你可以新建一些边,费用等于两个端点的欧几里得距离平方.另外还有\(q(q<=8)\)个套餐可以购买,如 ...
- UVA 1151 买还是建(最小生成树)
买还是建 紫书P358 [题目链接]买还是建 [题目类型]最小生成树 &题解: 这题真的心累,看了3天,最后照着码还是wa,先放lrj代码,以后再看吧 &代码: // UVa1151 ...
- UVa 1151 买还是建
https://vjudge.net/problem/UVA-1151 题意: 平面上有n个点,你的任务是让所有n个点连通.为此,你可以新建一些边,费用等于两个端点的距离平方和.另外还有q个套餐可以购 ...
- uva 1511 最小生成树
https://vjudge.net/problem/UVA-1151 题意,给出N个点以及二维坐标,可以在任意两点间建立通路,代价是两点欧几里得距离的平方,同时有q个套餐,套餐x有qx个点,代价是q ...
随机推荐
- 查一下 excel中某一列是否有重复
另一列中写入 =IF(COUNTIF(C:C,C1)>1,"有重复","") 其余往下拖拉公式 我在想如果可以有不往下拖的呢? 不过好像筛选中也有类似的选 ...
- 使用RoboCopy 命令
经常进行文件管理操作的朋友们,不满意于Windows系统内置的复制功能,因为它太龟速了.于是大家就使用FastCopy.TeraCopy之类的软件来加速复制,但是你是否知道Windows 7已经内置快 ...
- base64 encoding
//https://en.wikipedia.org/wiki/Base64 std::string base64Encode(const std::vector<char>& b ...
- Ubuntu 升级到13.10之后出现Apache2启动失败的问题
昨天看到Ubuntu 13.04提示有新的发行版Ubuntu 13.10了,手痒了一下,没有忍住就升级了. 结果升级完毕之后发现Apache2服务启动失败了,失败信息是: Invalid comman ...
- Java并发编程-关卡
CyclicBarrier 直译过来叫循环栅栏,它主要的方法就是一个:await().await() 方法没被调用一次,计数便会减少1,并阻塞住当前线程.当计数减至0时,阻塞解除,所有在此 Cycli ...
- 操作符重载.xml
pre{ line-height:1; color:#1e1e1e; background-color:#d2d2d2; font-size:16px;}.sysFunc{color:#627cf6; ...
- 学习Python必须要知道的常用模块
在程序设计中,为完成某一功能所需的一段程序或子程序:或指能由编译程序.装配程序等处理的独立程序单位:或指大型软件系统的一部分.本文为你介绍了Python中的两种常用模块. os: 这个模块包含普遍的操 ...
- 数往知来 ASP.NET_多线程_Socket<十五>
一.ASP.NET B/S 做网站(动态).管理系统(OA,进销存等) C/S--窗体软件 为什么现在很少用C/S做进销存等软件 B/S部署方便 C/S要安装 动态:与服务器(IIS(软件))进 ...
- vim开发环境配置
一.大饱眼福 看了效果图,肯定有人说, 这都有啥功能?就花哨? 告诉你,你说花哨就错了,开玩笑?我们程序猿可都是实打实的人,说谎都不会,咋会忽悠人呢. 下面我来告诉你,这都有些什么功能: 文件索引功能 ...
- static public和 public static 区别
static:加static 的是静态成员,不能实例化在你运行的时候他自己在内存中开辟了块空间,不用在new, 有点像全局变量,如果不用你必须去 实例化(new)才能用 static是静态的意思,pu ...