UVa1151&POJ2784--Buy or Build【kruskal+二进制枚举】
来源:互联网 发布:二分查找java 编辑:程序博客网 时间:2024/05/18 09:02
链接:
UVa http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3592
POJ http://poj.org/problem?id=2784
题意:告诉你n个点的坐标,建立一颗最小生成树,不过有q个套餐,套餐是连通某些点,并有一定花费,求最小生成树。
思路:n个点,n最大为1000,则最多有1000*999/2条边,先不使用套餐求一遍最小生成树,保留下最小生成树的边,此时最多有999条边,然后枚举每种套餐选或者不选,因为只有两种情况,用二进制枚举就行了,然后从筛选出的最多999条边里选边构造最小生成树。
#include<cstring>#include<string>#include<fstream>#include<iostream>#include<iomanip>#include<cstdio>#include<cctype>#include<algorithm>#include<queue>#include<map>#include<set>#include<vector>#include<stack>#include<ctime>#include<cstdlib>#include<functional>#include<cmath>using namespace std;#define PI acos(-1.0)#define MAXN 5000100#define eps 1e-7#define INF 0x7FFFFFFF#define LLINF 0x7FFFFFFFFFFFFFFF#define seed 131#define MOD 1000000007#define ll long long#define ull unsigned ll#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1struct node{ int u,v; int w;}edge[MAXN],edge2[1010];int n,m,q,ans;int qc[10][1010],qn[10],qm[10];int x[1010],y[1010],father[1010];bool cmp(node x,node y){ return x.w<y.w;}int Find(int x){ int t = x; while(t!=father[t]) t = father[t]; int k = x; while(k!=t){ int temp = father[k]; father[k] = t; k = temp; } return t;}void init(){ for(int i=0;i<=n;i++) father[i] = i;}int kruskal(){ int i,j; int sum = 0; int tot = 0; for(i=0;i<m;i++){ int a = Find(edge[i].u); int b = Find(edge[i].v); if(a!=b){ father[a] = b; edge2[sum] = edge[i]; tot += edge[i].w; sum++; if(sum>=n-1) break; } } return tot;}int gao(int x){ int i,j; int sum = 0; int tot = 0; for(i=0;i<q;i++){ if(x&(1<<i)){ tot += qm[i]; for(j=0;j<qn[i]-1;j++){ int aa = Find(qc[i][j]); int bb = Find(qc[i][j+1]); if(aa!=bb){ father[aa] = bb; sum++; } } } } for(i=0;i<n-1;i++){ int aa = Find(edge2[i].u); int bb = Find(edge2[i].v); if(aa!=bb){ father[aa] = bb; sum++; tot += edge2[i].w; if(sum>=n-1) break; } } //cout<<tot<<endl; return tot;}int main(){ int t,i,j; scanf("%d",&t); for(int iii=0;iii<t;iii++){ if(iii) puts(""); m = 0; scanf("%d%d",&n,&q); for(i=0;i<q;i++){ scanf("%d%d",&qn[i],&qm[i]); for(j=0;j<qn[i];j++){ scanf("%d",&qc[i][j]); } } for(i=1;i<=n;i++){ scanf("%d%d",&x[i],&y[i]); for(j=1;j<i;j++){ int temp = (x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]); edge[m].u = i; edge[m].v = j; edge[m].w = temp; m++; } } sort(edge,edge+m,cmp); init(); ans = kruskal(); for(i=0;i<(1<<q);i++){ init(); int temp = gao(i); ans = min(ans,temp); } printf("%d\n",ans); } return 0;}
0 0
- UVa1151&POJ2784--Buy or Build【kruskal+二进制枚举】
- POJ2784&&UVA1151-Buy or Build
- [最小生成树+二进制枚举]UVa1151 - Buy or Build
- Uva1151——Buy or Build && POJ2784——Buy or Build
- 【UVA1151】Buy or Build(MST+子集枚举)
- 买还是建buy or build,uva1151——最小生成树,Kruskal,枚举子集
- uva1151 Buy or Build
- UVA1511 Buy or Build 二进制枚举+最小生成树kruskal
- Kruskal+二进制枚举 POJ 2784 Buy or Build
- UVA1151[Buy or Build] 子集枚举+最小生成树
- uva-1151-Buy or Build-二进制枚举子集,并查集,最小生成树,kruskal
- Poj(2784),二进制枚举+最小生成树kruskal Buy or Build
- Uva1151.Buy or Build (最小生成树)
- 二进制枚举+prim buy or build 问题
- UVA 1151 Buy or Build(生成树+二进制枚举)
- uva 1151 Buy or Build 克鲁斯卡尔+二进制枚举
- 【UVA】1151 - Buy or Build(二进制枚举子集 + 并查集)
- UVA 1151 && POJ 2784 - Buy or Build 最小生成树 二进制枚举
- Android与服务器通讯:如何保证两端时间一致性
- Delphi 安装ICS
- HDU Bone Collector 2620 01背包
- CentOS平台实现Nagios+NagiosQL监控
- VBA 读取/写入文本文件
- UVa1151&POJ2784--Buy or Build【kruskal+二进制枚举】
- POJ 3498 March of the Penguins(枚举+最大流)
- java的匿名内部类
- 2013成都站F题||hdu4786 并查集 生成树
- 代码块使用方式
- 故事公园-—昆明莲花池
- 打开程序员之门
- Hbase存储架构(整理)<转>
- 基于角色访问控制RBAC(上篇)