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


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

    首先想kruskal算法中,被加入的边已经是最优的了,所以当选择完套餐后,之前被丢弃的边也不会再进入最小生成树

    然后就可以先求一次原图的最小生成树,保存下进入最小生成树的n-1条边

    再枚举选择的套餐的情况,再求最小生成树,这里用的二进制法枚举 最后维护一个最小值就可以了

    思路虽然看懂了,可是代码根本就写不出来,看着标程写的,最后还是改了那么久-- sad----------

      1 #include<iostream>  
      2 #include<cstdio>  
      3 #include<cstring> 
      4 #include <cmath> 
      5 #include<stack>
      6 #include<vector>
      7 #include<map> 
      8 #include<set>
      9 #include<queue> 
     10 #include<algorithm>  
     11 using namespace std;
     12 
     13 #define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
     14 
     15 typedef long long LL;
     16 const int INF = (1<<30)-1;
     17 const int mod=1000000007;
     18 const int maxn=1005;
     19 const int maxq=8;
     20 
     21 int n;
     22 int x[maxn],y[maxn],cost[maxn];
     23 vector<int> subn[maxn];
     24 
     25 int p[maxn];
     26 int find(int x) {return p[x]!=x? p[x]=find(p[x]):x;}
     27 
     28 struct edge{
     29     int u,v,d;
     30     edge(int u,int v,int d):u(u),v(v),d(d) {}
     31     bool operator <(const edge& rhs) const{
     32     return d<rhs.d;}
     33 };
     34 
     35 int mst(int cnt,const vector<edge>& e,vector<edge>& used){
     36     if(cnt==1) return 0;
     37     int m=e.size();
     38     int ans=0;
     39     used.clear();
     40     for(int i=0;i<m;i++){
     41         int u=find(e[i].u),v=find(e[i].v);
     42         int d=e[i].d;
     43         if(u!=v){
     44             p[u]=v;
     45             ans+=d;
     46             used.push_back(e[i]);
     47             if(--cnt==1) break;
     48         }
     49     }
     50     return ans;
     51 }
     52 
     53 int main(){
     54 //    freopen("in.txt","r",stdin);
     55 //    freopen("outttttttt.txt","w",stdout);
     56     int T,q;
     57     scanf("%d",&T);
     58     while(T--){
     59         scanf("%d%d",&n,&q);
     60         for(int i=0;i<q;i++){
     61             int cnt;
     62             scanf("%d %d",&cnt,&cost[i]);
     63             subn[i].clear();
     64             while(cnt--){
     65                 int u;
     66                 scanf("%d",&u);
     67                 subn[i].push_back(u-1);            
     68             }
     69         }
     70         
     71         for(int i=0;i<n;i++) scanf("%d %d",&x[i],&y[i]);
     72         
     73         vector<edge> e,need;
     74         
     75         for(int i=0;i<n;i++)
     76          for(int j=i+1;j<n;j++){
     77              int c=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
     78              e.push_back(edge(i,j,c));
     79          }
     80         
     81         for(int i=0;i<n;i++) p[i]=i;
     82         sort(e.begin(),e.end());
     83         
     84         int ans=mst(n,e,need);
     85         
     86         for(int mask=0;mask<(1<<q);mask++){
     87             
     88             for(int i=0;i<n;i++) p[i]=i;
     89             int cnt=n,c=0;
     90             
     91             for(int i=0;i<q;i++) if(mask & (1<<i)){
     92                 c+=cost[i];
     93                 for(int j=1;j<subn[i].size();j++){
     94                     int u=find(subn[i][j]),v=find(subn[i][0]);
     95                     if(u!=v){p[u]=v;cnt--;}
     96                 }
     97             }
     98             vector<edge> dummy;
     99             ans=min(ans,c+mst(cnt,need,dummy));
    100         }
    101         printf("%d
    ",ans);
    102         if(T) printf("
    ");        
    103     }
    104     return 0;    
    105 }
    View Code
  • 相关阅读:
    Linux普通用户登录后,命令行提示:-bash-4.1$ ,原因分析及解决
    ps命令
    Linux命令ping
    Linux 系统管理 : last 命令详解
    Linux命令head
    Linux more与less命令
    Mac下开启Chrome非安全模式
    mac host 修改
    mac 电脑记
    a的样式顺序
  • 原文地址:https://www.cnblogs.com/wuyuewoniu/p/4475078.html
Copyright © 2020-2023  润新知