买还是建buy or build,uva1151——最小生成树,Kruskal,枚举子集
来源:互联网 发布:期货 期权 知乎 编辑:程序博客网 时间:2024/05/22 03:30
平面上有n个点(1<=N<=1000),你的任务是让所有n个点连通,为此,你可以新建一些边,费用等于两个端点的欧几里得距离的平方。另外还有q(0<=q<=8)个套餐,可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相互连通,第i个套餐的花费为ci。
kruskal:
先求一次原图的最小生成树,得到n-1条边,然后每次枚举完套餐后只考虑套餐中的边和这n-1条边,则枚举套餐之后再求最小生成树。
精髓:kruskal算法中,那些两端已经属于同一个连通分量的边不会再加到生成树里面。
那么买了套餐后,相当于一些边的权变为0,而对于不在套餐中的每条边e,排序在e之前的边一个也没少,反而可能多了一些权值为0的边。
所以在 原图kruskal时被扔掉的边,在购买套餐后的Kruskal中也一样会被扔掉
二进制枚举子集
for(int i=0;i<(1<<n);++i){
for(int j=0;j<n;++j){
if(i&(1<<j)) printf("%d ",j);
}
puts(" ");
}
WA的代码,找不出错误,标记一下
#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<cmath>#define REP(i,n) for(int i=0;i<(n);++i)#define FOR(i,a,b) for(int i=(a);i<(b);++i)#define FORD(i,a,b) for(int i=(a);i<=(b);++i)#define mes(s,c) memset(s,c,sizeof(s))const int maxn=1010;const int INF=1<<30;using namespace std;int MST_w;int n,m;int f[maxn];struct Edge{ int u,v; int w; Edge(int from,int to,int d):u(from),v(to),w(d){} bool operator<(const Edge&x)const{ return w<x.w; }};vector<Edge> edges;struct val{ int node[maxn]; int cnt; int w;}c[10];vector<pair<int,int> >node;void makeSet(){REP(i,n+1)f[i]=i;}int find(int x){ return f[x]==x?x:f[x]=find(f[x]);}int MST[maxn];void kruskal(){ sort(edges.begin(),edges.end()); makeSet();int cnt=0; MST_w=0; REP(i,edges.size()){ int f_u=find(edges[i].u); int f_v=find(edges[i].v); if(f_u!=f_v){ f[f_u]=f_v; MST[cnt++]=i; MST_w+=edges[i].w; if(cnt==n-1) break; } }// cout<<"最小生成树=="<<MST_w<<endl;}void _kruskal(int &w){ REP(i,n-1){ int f_u=find(edges[MST[i]].u); int f_v=find(edges[MST[i]].v); if(f_u!=f_v){ w+=edges[MST[i]].w; f[f_u]=f_v; } }}void solve(){ int ans=MST_w; REP(i,1<<m){ makeSet(); int w=0; REP(j,m){ if(i&(1<<j)){//枚举子集 w+=c[j].w; REP(k,c[j].cnt-1){//将套餐中的点连通 int f_u=c[j].node[k]; int f_v=c[j].node[k+1]; if(f_u!=f_v) f[f_u]=f_v; } } }//最小生成树 _kruskal(w); ans=min(ans,w); } printf("%d\n",ans);}int main(){#ifndef ONLINE_JUDGEfreopen("in.cpp","r",stdin);#endif // ONLINE_JUDGE scanf("%d%d",&n,&m); node.clear();edges.clear(); REP(i,m){scanf("%d%d",&c[i].cnt,&c[i].w);REP(j,c[i].cnt)scanf("%d",&c[i].node[j]);}//输入套餐 REP(i,n){//输入点坐标 int x,y; scanf("%d%d",&x,&y); node.push_back(make_pair(x,y)); } REP(i,n)FOR(j,i+1,n){//预处理边权 int x=int(node[i].first-node[j].first); int y=int(node[i].second-node[j].second); int w=x*x+y*y; edges.push_back(Edge(i+1,j+1,w)); } kruskal();//求原图的MST,记录边的序号 solve(); return 0;}
0 0
- 买还是建buy or build,uva1151——最小生成树,Kruskal,枚举子集
- UVA1151[Buy or Build] 子集枚举+最小生成树
- [最小生成树+二进制枚举]UVa1151 - Buy or Build
- Uva1151.Buy or Build (最小生成树)
- 【UVA1151】Buy or Build(MST+子集枚举)
- uva-1151-Buy or Build-二进制枚举子集,并查集,最小生成树,kruskal
- UVA1511 Buy or Build 二进制枚举+最小生成树kruskal
- UVa1151&POJ2784--Buy or Build【kruskal+二进制枚举】
- UVA 1151 Buy or Build(最小生成树+枚举子集)
- Poj(2784),二进制枚举+最小生成树kruskal Buy or Build
- uva1151 最小生成树kruskal
- uva1151 Buy or Build
- UVA1151buy or build 最小生成树+子集枚举
- Uva1151——Buy or Build && POJ2784——Buy or Build
- POJ2784&&UVA1151-Buy or Build
- UVA 1151 - Buy or Build(最小生成树,二进制子集生成)
- 最小生成树,Kruskal(买还是建 uva 1151)
- UVA 1151 Buy or Build 最小生成树+二进制选取子集
- 使用curl解压gzip的内容
- JAVASE之集合框架-----List
- 一篇很全面的freemarker教程(收藏)
- 【MATLAB】pagerank算法
- ROS 学习系列 -- 使用urdf创建机器人模型在Rviz中3D观察 之二 joint 使用
- 买还是建buy or build,uva1151——最小生成树,Kruskal,枚举子集
- 小P的故事——神奇的分组 背包
- Jquery 删除元素remove() detach() empty()比较
- lingo解决6个发点8个收点的最小运输费用问题
- 局域网聊天室
- HDU 1031 Design T-Shirt
- POJ3278Catch That Cow(线性模型)(BFS)
- 写给初学者的A*算法(A*Pathfinding for beginners)
- 用百度map api展示时空数据(一)