题意很简单:要求一个比值最大的情况,因为节点的个数最多只有15个,所以我们可以暴力枚举所有的情况,然后对每一种情况求出最小生成树,最后输出结果就好了。
另外这道题还有个很奇葩的东西,就是比值的小数点要到1e-9,正常的比较大小无法满足需要,我们需要通过if(wei1-answ<-(1e-9))的判断方法来解决这个问题。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define N 18
#define INF 0x7fffffff
using namespace std;
int len[N][N],m,n,weight[N],ans[N],G[N],answer[N];
double wei1,wei2,answ;
struct node
{
int a, b;
int len;
}Node[N*N];
bool cmp(node a,node b)
{
return a.len<b.len;
}
int findx(int x)
{
return G[x]==x?x:G[x]=findx(G[x]);
}
double get()
{
int i,t=0;
wei1=wei2=0;
for(i=0;i<n;i++)
{
wei1+=weight[ans[i]];
G[ans[i]]=ans[i];
}
for(i=0;i<n;i++)
for(int j=i+1;j<n;j++)
{
Node[t].a=ans[i];
Node[t].b=ans[j];
Node[t].len=len[ans[i]][ans[j]];
t++;
}
if(t!=1) sort(Node,Node+t,cmp);
for(i=0;i<t;i++)
{
int p=findx(Node[i].a),
q=findx(Node[i].b);
if(p!=q)
{
wei2+=Node[i].len;
G[p]=q;
}
}
wei1=wei2/wei1;
if(wei1-answ<-(1e-9))
{
answ=wei1;
for(t=0;t<n;t++)
{
answer[t]=ans[t];
}
}
}
void dfs(int i)
{
int t;
if(i>=n)
{
get();
return ;
}
if(i==0)
{
for(t=0;t<=m-n;t++)
{
ans[i]=t;
dfs(i+1);
}
}
else
{
for(t=ans[i-1]+1;t<m;t++)
{
ans[i]=t;
dfs(i+1);
}
}
}
int main()
{
while(scanf("%d %d",&m,&n) )
{
if(m==n &&n==0) break;
int i;
for(i=0;i<m;i++) scanf("%d",&weight[i]);
for(i=0;i<m;i++)
for(int j=0;j<m;j++)
scanf("%d",&len[i][j]);
answ=INF;
dfs(0);
sort(answer,answer+n);
printf("%d",answer[0]+1);
for(i=1;i<n;i++)
printf(" %d",answer[i]+1);
printf("\n");
}
return 0;
}