UVA 1151Buy or Build MST
来源:互联网 发布:云朵课堂下载软件 编辑:程序博客网 时间:2024/06/06 16:42
题意:
在平面上有n个点,要让所有n个点都连通,所以你要构造一些边来连通他们,连通的费用等于两个端点的欧几里得距离的平方。另外还有q个套餐,可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相互连通,第i个套餐的花费为ci。求最小花费。
思路:
在这里我们可以采取枚举所有可能 + K算法来得出答案,比如这里有三个套餐,我们利用二进制枚举001、010、011 、100、 101、 110、 111 分别代表第一个和第二个不要,要第三个(001);不要第一个和第三个,要第二个(010).......即 0 代表不要, 1 代表要,然后把要的套餐中的所有点都连通,再用K算法求剩下的未连接的点的最小生成树。
注意:
在套餐中合并点时不能单纯地让pre[i] = pre[1](i > 1);pre[i]数组代表 pre[i] 和 i 在一个集合里面(并查集);举个栗子:
有一个套餐是:
4 10 2 3 4 5
含义是购买这个套餐中可以让四个点连通,分别是2,3,4,5号点,费用为 10;如果让 pre[3] = pre[4]=pre[5] = 2;
那么假设还有个套餐:
3 9 1 5 3
含义如上 ,如果再写pre[5] = pre[3] = 1;那么假设我购买了这俩个套餐,本应该2 3 4 5 1都在一个集合里面的,但是按照上面那么写 则 2 4 是一个集合, 1 3 5 是一个集合。不符合我的意思,所以购买套餐合并里面的点时应该写成pre[i] = Find(pre[1]);前提是这俩个不在一个集合里面。
代码:
<pre name="code" class="cpp">#include <bits/stdc++.h> #define prln(x) cout<<(x)<<endl using namespace std; typedef long long LL; const double PI = acos(-1); const double ESP = 1e-8; const int MAXN = 1000 + 3; const int MOD = 1e9 + 7; int pre[MAXN]; typedef struct Point{ //题目中给的点 int x; int y; }Po; typedef struct Buy{ //套餐 int m; //购买该套餐可以合并点的个数 int ci; //购买该套餐的费用 int a[MAXN]; //这个套餐可以合并的点的编号 int flag; //是否要购买这个套餐,对每个套餐的这个值进行二进制枚举 }Bu; typedef struct City{ //用来存储图 int u; int v; int w; }Ci; Ci edge[MAXN * MAXN / 2 + 3]; Po pt[MAXN]; Bu buy[11]; int Find(int x) //并查集 { return x == pre[x] ? x : pre[x] = Find(pre[x]); } void Stpre(int n) { for(int i = 0; i <= n; i++) pre[i] = i; } void Ststu(){ memset(&pt,0,sizeof(Po)); memset(&buy,0,sizeof(Bu)); memset(&edge,0,sizeof(Ci));}int Ojld(Point a, Point b){ int xx = a.x - b.x; int yy = a.y - b.y; return xx * xx + yy *yy;}int mycmp(City a, City b){ return a.w < b.w;}int ksu(int l)//K算法{ int ans= 0; for(int i = 1; i<= l; i++) { int fv = Find(edge[i].v); int fu = Find(edge[i].u); if(fu != fv) { pre[fu] = pre[fv]; ans += edge[i].w; } } return ans;}int main(){ //freopen("input.txt","r",stdin); int t; cin >> t; while(t--) { Ststu(); int n, q; scanf("%d%d",&n, &q); for(int i = 1; i <= q; i++) { scanf("%d",&buy[i].m); scanf("%d",&buy[i].ci); for(int j = 1; j <= buy[i].m; j++) scanf("%d",&buy[i].a[j]); } for(int i = 1; i <= n; i++) scanf("%d%d",&pt[i].x, &pt[i].y); int sum = 0; for(int i = 1; i < n; i++) { for(int j = i + 1; j <= n; j++) { sum++; edge[sum].u = i; edge[sum].v = j; edge[sum].w = Ojld(pt[i], pt[j]); //printf("%d %d %d %d\n",sum,i,j,edge[sum].w); } } sort(edge + 1, edge + sum + 1 , mycmp); int ans = 0x7F7F7F7F; for(int i = 0; i < (1 << q); i++) //二进制枚举 { Stpre(n); int temp = i; int mst = 0; for(int j = 1; j <= q; j++) { if(temp & 1) { mst += buy[j].ci; for(int k = 2; k <= buy[j].m; k++) { int fx = Find ( buy[j].a[1] ); int fy = Find( buy[j].a[k] ); if(fy != fx) pre[fy] = pre[fx]; } } temp >>= 1; } mst += ksu(sum); ans = min(ans, mst); } printf("%d\n",ans); if(t)prln(""); } return 0;}
- UVA 1151Buy or Build MST
- uva 1151 Buy or Build
- UVA 1151 Buy or Build
- UVa 1151 Buy or Build
- UVA 1151 Buy or Build
- UVa 1151 Buy or Build
- uva 1151 Buy or Build
- Buy or Build UVA
- Buy or Build UVA
- 【UVA1151】Buy or Build(MST+子集枚举)
- (Uva)Buy or Build(B)
- uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)
- 1151 - Buy or Build
- UVa #1151 Buy or Build (例题11-3)
- uva 1151 Buy or Build (最小生成树)
- UVA 1151 Buy or Build(生成树+二进制枚举)
- UVa 1151 Buy or Build (最小生成树)
- uva 1151 Buy or Build 状压枚举
- 电源设计之buck变换(一)
- A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS(试译)
- 退出telnet命令
- Shell Script 学习整理
- ZOJ 3876 May Day Holiday(找规律||打表-基姆拉尔森计算公式(求某年某月某日星期几))
- UVA 1151Buy or Build MST
- Hessian海森矩阵与牛顿最优化方法
- BestCoder Round #78 1001/ hdu 5655 CA Loves Stick
- MySQL 学习笔记(1)2016-04-02
- maven的使用
- hdu1171 Big Event in HDU(多重背包)
- ColorEditText
- 你在公司项目里面看到过哪些操蛋的代码?
- [从头学数学] 第159节 反比例函数 小结与复习题