Minimal Ratio Tree

hdu2489:http://acm.hdu.edu.cn/showproblem.php?pid=2489

题意:给你一个n个节点图,图的点有边权和点权,然后选取m个节点的子图,然后求这个一棵树,然后让这棵树的所有边权之和/所有点权之和的值最少。

题解:n很小,只有15,所以可以直接暴力,枚举每一种情况,然后求每一种情况的最小生成树,取最小的就可以了。但是这里的学到一个新的东西。就是判断a<b的时候,有可能a==b的时候由于浮点误差,也会被判成a<b,但是题目要的是字典序最小的,所以相等的时候是不能取的,所以要先考虑a和b是否相等,在不等的情况下在进行a<b的判断。

  1 #include<cstring>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<cmath>
  6 using namespace std;
  7 int fa[30],node[30],ans[30],val[30],g[30][30];
  8 int n,m;
  9 double last;
 10 void init(){
 11    for(int i=1;i<=15;i++)
 12       fa[i]=i;
 13 }
 14 int Find(int x){
 15   int s;
 16   for(s=x;s!=fa[s];s=fa[s]);
 17   while(x!=s){
 18     int temp=fa[x];
 19     fa[x]=s;
 20     x=temp;
 21   }
 22   return s;
 23 }
 24 struct Node{
 25   int x,y;
 26   int w;
 27   bool operator<(const Node a)const{
 28     return w<a.w;
 29   }
 30 }num[300];
 31 void solve(int *a){
 32     int top=0,cost=0;
 33     for(int i=1;i<=n;i++)
 34      if(a[i])cost+=val[i];
 35 
 36    for(int i=1;i<=n;i++)
 37       for(int j=1;j<=n;j++)
 38       if(a[i]&&a[j]&&g[i][j]){
 39          num[++top].x=i;
 40          num[top].y=j;
 41          num[top].w=g[i][j];
 42    }
 43    sort(num+1,num+top+1);
 44    int ct1=0,ct2=0;
 45    init();
 46    for(int i=1;i<=top;i++){
 47         int tx=Find(num[i].x);
 48         int ty=Find(num[i].y);
 49        if(tx==ty)continue;
 50        else{
 51           fa[tx]=ty;
 52           ct1+=num[i].w;
 53           ct2++;
 54           if(ct2==m-1)break;
 55        }
 56    }
 57    if(ct2==m-1){
 58         double temp=(double)ct1/(double)cost;
 59       if(abs(temp-last)>0.00000001&&temp<last){
 60         last=temp;
 61         memset(ans,0,sizeof(ans));
 62         for(int i=1;i<=n;i++)
 63             if(a[i])
 64             ans[i]=i;
 65       }
 66    }
 67 }
 68 void DFS(int depth,int start){
 69     if(depth==m+1){
 70         solve(node);
 71         return;
 72     }
 73     for(int i=start;i<=n;i++){
 74         node[i]=1;
 75         DFS(depth+1,i+1);
 76         node[i]=0;
 77     }
 78 }
 79 int main(){
 80    while(~scanf("%d%d",&n,&m)&&n){
 81        memset(g,0,sizeof(g));
 82        memset(ans,0,sizeof(ans));
 83        memset(node,0,sizeof(node));
 84        for(int i=1;i<=n;i++)
 85           scanf("%d",&val[i]);
 86        for(int i=1;i<=n;i++)
 87           for(int j=1;j<=n;j++)
 88              scanf("%d",&g[i][j]);
 89              last=100000000.0;
 90              DFS(1,1);
 91              int aa=0;
 92       for(int i=1;i<=n;i++)
 93         if(ans[i]){
 94            if(!aa)printf("%d",ans[i]);
 95            else
 96           printf(" %d",ans[i]);
 97           aa=1;
 98         }
 99           puts("");
100    }
101 }
View Code

 

posted on 2014-08-15 09:57  天依蓝  阅读(284)  评论(0编辑  收藏  举报

导航