您的位置:首页 > 产品设计 > UI/UE

UVa 1151 Buy or Build【最小生成树】

2015-05-03 23:49 357 查看
题意:给出n个点的坐标,现在需要让这n个点连通,可以直接在点与点之间连边,花费为两点之间欧几里得距离的平方,也可以选购套餐,套餐中所含的点是相互连通的 问最少的花费

首先想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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: