zoukankan      html  css  js  c++  java
  • hdu 2489 Minimal Ratio Tree

    https://vjudge.net/problem/HDU-2489

    题意:求一个完全图的最优比率生成树,点的个数由题给出。最优比率生成树是边的权值之和与点的权值之和的比值最小的生成树。

    思路:一开始用dfs枚举搜索每一种情况,t了,枚举的情况太多。之后看了题解,用的是状态压缩的方法枚举点的选择,这样的情况要少得多。至于其他的细节倒是很好想,由于比值最小,所以我们要求的是一棵最小生成树,再比上点的权值之和,最后选择出最小的就行了。

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <map>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 int n,m;
      8 
      9 int par[20];
     10 int a[20][20];
     11 int b[20];
     12 
     13 struct node
     14 {
     15     int x,y,d;
     16 } g[1000];
     17 
     18 void init(int k)
     19 {
     20     for (int i = 0;i <= k;i++)
     21         par[i] = i;
     22 }
     23 
     24 int fin(int x)
     25 {
     26     if (x == par[x]) return x;
     27     else return par[x] = fin(par[x]);
     28 }
     29 
     30 void unit(int x,int y)
     31 {
     32     x = fin(x);
     33     y = fin(y);
     34 
     35     if (x != y) par[x] = y;
     36 }
     37 
     38 bool cmp(node aa,node bb)
     39 {
     40     return aa.d < bb.d;
     41 }
     42 
     43 double solve(int k)
     44 {
     45     init(n);
     46 
     47     int p[20],cnt = 0;
     48     int num = 0;
     49 
     50     for (int i = 0;i < n;i++)
     51     {
     52         if (k & (1 << i)) p[cnt++] = i;
     53     }
     54 
     55     for (int i = 0;i < cnt;i++)
     56     {
     57         for (int j = i + 1;j < cnt;j++)
     58         {
     59             g[num].x = p[i];
     60             g[num].y = p[j];
     61             g[num].d = a[p[i]][p[j]];
     62             num++;
     63         }
     64     }
     65 
     66     int sum = 0,sm = 0;
     67 
     68     for (int i = 0;i < cnt;i++)
     69     {
     70         int t = p[i];
     71         sum += b[t];
     72     }
     73 
     74     sort(g,g+num,cmp);
     75 
     76     for (int i = 0;i < num;i++)
     77     {
     78         int x = g[i].x,y = g[i].y;
     79 
     80         //printf("%d %d88
    ",x,y);
     81 
     82         if (fin(x) == fin(y)) continue;
     83 
     84         unit(x,y);
     85 
     86         sm += g[i].d;
     87     }
     88 
     89     return 1.0 * sm / sum;
     90 }
     91 
     92 int main()
     93 {
     94     while (scanf("%d%d",&n,&m) != EOF)
     95     {
     96         double minn = 10000000000;
     97 
     98         if (!m && !n) break;
     99 
    100 
    101         for (int i = 0;i < n;i++)
    102             scanf("%d",&b[i]);
    103 
    104         for (int i = 0;i < n;i++)
    105             for (int j = 0;j < n;j++)
    106             scanf("%d",&a[i][j]);
    107 
    108         int ba = (1 << n) - 1;
    109 
    110         for (int i = 3;i <= ba;i++)
    111         {
    112             int num = 0;
    113 
    114             for (int j = 0;j < n;j++)
    115             {
    116                 if (i & (1 << j)) num++;
    117             }
    118 
    119             if (num == m)
    120             {
    121                 //0printf("00
    ");
    122                 double tmp = solve(i);
    123 
    124                 if (tmp < minn)
    125                 {
    126                     minn = tmp;
    127                 }
    128             }
    129         }
    130 
    131         int mark;
    132 
    133         for (int i = 3;i <= ba;i++)
    134         {
    135             int num = 0;
    136 
    137             for (int j = 0;j < n;j++)
    138             {
    139                 if (i & (1 << j)) num++;
    140             }
    141 
    142             if (num == m)
    143             {
    144                 double tmp = solve(i);
    145 
    146                 if (tmp == minn)
    147                 {
    148                     mark = i;
    149                     break;
    150                 }
    151             }
    152         }
    153 
    154         int p[20];
    155 
    156         int cnt = 0;
    157 
    158         for (int i = 0;i < n;i++)
    159         {
    160             if (mark & (1 << i)) p[cnt++] = i;
    161         }
    162 
    163         for (int i = 0;i < cnt;i++)
    164         {
    165             if (!i) printf("%d",p[i]+1);
    166             else printf(" %d",p[i]+1);
    167         }
    168 
    169         printf("
    ");
    170     }
    171 
    172     return 0;
    173 }

    再附上一份t了的代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <algorithm>
      4 #include <map>
      5 #include <vector>
      6 using namespace std;
      7 
      8 int n,m;
      9 int num = 0;
     10 int par[20];
     11 int a[20];
     12 int b[20][20];
     13 bool v[20];
     14 int s[20];
     15 vector<int> vv[10005];
     16 map<double,int> mmp;
     17 
     18 double minn;
     19 
     20 struct node
     21 {
     22     int x,y,d;
     23 } g[500];
     24 
     25 bool cmp(node aa,node bb)
     26 {
     27     return aa.d < bb.d;
     28 }
     29 
     30 void init(int k)
     31 {
     32     for (int i = 0;i <= k;i++)
     33         par[i] = i;
     34 }
     35 
     36 int fin(int x)
     37 {
     38     if (x == par[x]) return x;
     39     else return par[x] = fin(par[x]);
     40 }
     41 
     42 void unit(int x,int y)
     43 {
     44     x = fin(x);
     45     y = fin(y);
     46 
     47     if (x != y) par[x] = y;
     48 }
     49 
     50 void solve(void)
     51 {
     52     int cnt = 0;
     53 
     54     bool f = 0;
     55 
     56     init(n);
     57 
     58     for (int i = 0;i < m;i++)
     59         for (int j = i + 1;j < m;j++)
     60     {
     61         int x = s[i],y = s[j];
     62         if (b[x][y])
     63         {
     64             g[cnt].x = x;
     65             g[cnt].y = y;
     66             g[cnt].d = b[x][y];
     67             cnt++;
     68         }
     69     }
     70 
     71     int sum = 0;
     72 
     73     for (int i = 0;i < m;i++)
     74     {
     75         int t = s[i];
     76 
     77         sum += a[t];
     78     }
     79 
     80     sort(g,g+cnt,cmp);
     81 
     82     int sm = 0;
     83 
     84     for (int i = 0;i < cnt;i++)
     85     {
     86         int x = g[i].x,y = g[i].y;
     87 
     88         if (fin(x) == fin(y)) continue;
     89 
     90         sm += g[i].d;
     91 
     92         unit(x,y);
     93     }
     94 
     95     int rt = fin(s[0]);
     96 
     97     for (int i = 0;i < m;i++)
     98     {
     99         if (fin(s[i]) != fin(rt)) f = 1;
    100     }
    101 
    102     double now = 1.0 * sm / sum;
    103 
    104     if (!f && now < minn)
    105     {
    106         if (!mmp[now])
    107         {
    108             mmp[now] = num;
    109             minn = now;
    110 
    111             for (int i = 0;i < m;i++)
    112                 vv[num].push_back(s[i]);
    113 
    114             num++;
    115         }
    116 
    117     }
    118 }
    119 
    120 void dfs(int i,int p)
    121 {
    122     if (m == n && p == m - 1)
    123     {
    124         s[p] = i;
    125         solve();
    126         return;
    127     }
    128     else if (m < n && p == m)
    129     {
    130         solve();
    131         return;
    132     }
    133 
    134     s[p] = i;
    135 
    136     for (int j = 0;j < n;j++)
    137     {
    138         if (!v[j])
    139         {
    140             v[j] = 1;
    141             dfs(j,p+1);
    142             v[j] = 0;
    143         }
    144     }
    145 }
    146 
    147 
    148 int main()
    149 {
    150     while (scanf("%d%d",&n,&m) != EOF)
    151     {
    152         if (m == 0 && n == 0) break;
    153 
    154         num = 0;
    155 
    156         minn = 1000000000;
    157 
    158         memset(v,0,sizeof(v));
    159         memset(s,0,sizeof(s));
    160         memset(a,0,sizeof(a));
    161         memset(b,0,sizeof(b));
    162         memset(g,0,sizeof(g));
    163         memset(vv,0,sizeof(vv));
    164 
    165         for (int i = 0;i < n;i++)
    166             scanf("%d",&a[i]);
    167 
    168 
    169         for (int i = 0;i < n;i++)
    170             for (int j = 0;j < n;j++)
    171             scanf("%d",&b[i][j]);
    172 
    173         for (int i = 0;i < n;i++)
    174         {
    175             v[i] = 1;
    176             dfs(i,0);
    177             v[i] = 0;
    178         }
    179 
    180         int k = mmp[minn];
    181 
    182         sort(vv[k].begin(),vv[k].end());
    183 
    184         for (int i = 0;i < vv[k].size();i++)
    185         {
    186             if (!i) printf("%d",vv[k][i] + 1);
    187             else printf(" %d",vv[k][i] + 1);
    188         }
    189 
    190         printf("
    ");
    191     }
    192 
    193     return 0;
    194 }
    犹豫就会败北!
  • 相关阅读:
    13.Odoo产品分析 (二) – 商业板块(6) –采购(3)
    9.Odoo产品分析 (二) – 商业板块(4) –讨论(1)
    10.Odoo产品分析 (二) – 商业板块(5) –日历(1)
    8.Odoo产品分析 (二) – 商业板块(3) –CRM(2)
    7.Odoo产品分析 (二) – 商业板块(3) –CRM(1)
    the nearest point/vertex point of linestring
    Clojure的引用类型:var,ref,agent和atom
    clojure的delay future promise
    clojure的语法糖
    postgres select TOP X in group 查询每个组的前几名
  • 原文地址:https://www.cnblogs.com/kickit/p/7150817.html
Copyright © 2011-2022 走看看