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\n",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\n");
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("\n");
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("\n");
191     }
192 
193     return 0;
194 }

 

posted @ 2017-07-11 15:32  qrfkickit  阅读(136)  评论(0编辑  收藏  举报