UVa 1151 Buy or Build【最小生成树】
2015-05-03 23:49
357 查看
题意:给出n个点的坐标,现在需要让这n个点连通,可以直接在点与点之间连边,花费为两点之间欧几里得距离的平方,也可以选购套餐,套餐中所含的点是相互连通的 问最少的花费
首先想kruskal算法中,被加入的边已经是最优的了,所以当选择完套餐后,之前被丢弃的边也不会再进入最小生成树
然后就可以先求一次原图的最小生成树,保存下进入最小生成树的n-1条边
再枚举选择的套餐的情况,再求最小生成树,这里用的二进制法枚举 最后维护一个最小值就可以了
思路虽然看懂了,可是代码根本就写不出来,看着标程写的,最后还是改了那么久-- sad----------
View Code
首先想kruskal算法中,被加入的边已经是最优的了,所以当选择完套餐后,之前被丢弃的边也不会再进入最小生成树
然后就可以先求一次原图的最小生成树,保存下进入最小生成树的n-1条边
再枚举选择的套餐的情况,再求最小生成树,这里用的二进制法枚举 最后维护一个最小值就可以了
思路虽然看懂了,可是代码根本就写不出来,看着标程写的,最后还是改了那么久-- sad----------
#include<iostream> #include<cstdio> #include<cstring> #include <cmath> #include<stack> #include<vector> #include<map> #include<set> #include<queue> #include<algorithm> using namespace std; #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i) typedef long long LL; const int INF = (1<<30)-1; const int mod=1000000007; const int maxn=1005; const int maxq=8; int n; int x[maxn],y[maxn],cost[maxn]; vector<int> subn[maxn]; int p[maxn]; int find(int x) {return p[x]!=x? p[x]=find(p[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;} }; int mst(int cnt,const vector<edge>& e,vector<edge>& used){ if(cnt==1) return 0; int m=e.size(); int ans=0; used.clear(); for(int i=0;i<m;i++){ int u=find(e[i].u),v=find(e[i].v); int d=e[i].d; if(u!=v){ p[u]=v; ans+=d; used.push_back(e[i]); if(--cnt==1) break; } } return ans; } int main(){ // freopen("in.txt","r",stdin); // freopen("outttttttt.txt","w",stdout); int T,q; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&q); for(int i=0;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-1); } } for(int i=0;i<n;i++) scanf("%d %d",&x[i],&y[i]); vector<edge> e,need; for(int i=0;i<n;i++) for(int j=i+1;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)); } for(int i=0;i<n;i++) p[i]=i; sort(e.begin(),e.end()); int ans=mst(n,e,need); for(int mask=0;mask<(1<<q);mask++){ for(int i=0;i<n;i++) p[i]=i; int cnt=n,c=0; for(int i=0;i<q;i++) if(mask & (1<<i)){ c+=cost[i]; for(int j=1;j<subn[i].size();j++){ int u=find(subn[i][j]),v=find(subn[i][0]); if(u!=v){p[u]=v;cnt--;} } } vector<edge> dummy; ans=min(ans,c+mst(cnt,need,dummy)); } printf("%d\n",ans); if(T) printf("\n"); } return 0; }
View Code
相关文章推荐
- uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)
- Buy or Build UVA - 1151 MST最小生成树
- uva-1151-Buy or Build-二进制枚举子集,并查集,最小生成树,kruskal
- 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 MST(最小生成树)
- 买还是建buy or build,uva1151——最小生成树,Kruskal,枚举子集
- UVA 1151 Buy or Build (最小生成树)
- UVa 1151 Buy or Build (最小生成树+二进制法暴力求解)
- uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)
- 紫书 - UVA - 1151 Buy or Build 最小生成树+状态枚举
- uva 1151 Buy or Build (最小生成树)
- UVA 1151 Buy or Build (MST最小生成树,kruscal,变形)
- uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)
- 1151 - Buy or Build (最小生成树)
- UVA1511 Buy or Build 二进制枚举+最小生成树kruskal
- UVA 1151 Buy or Build(生成树+二进制枚举)
- UVA 1151 && POJ 2784 - Buy or Build 最小生成树 二进制枚举