哎 直接枚举所有m个点 求最小生成树
按题意来就行了。。
另外还要加一个剪枝
在存点的编号 用点的编号的地方wa了好久好久。。
#include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #define inf 0x3f3f3f3f #define ll __int64 using namespace std; int ans[20],d[20],vis[20],s[20],w[20],e[20][20],n,m; double rat; void prim() { int i,j,t,minweight,p,tmp,sum; memset(vis,0,sizeof vis); minweight=0; p=s[1];vis[p]=1;d[p]=0; for(i=1;i<=m;i++) if(s[i]!=p) d[s[i]]=e[p][s[i]]; for(i=1;i<m;i++) { tmp=inf; for(j=1;j<=m;j++) { t=s[j]; if(!vis[t]&&tmp>d[t]) { tmp=d[t]; p=t; } } vis[p]=1; minweight+=d[p]; for(j=1;j<=m;j++) { t=s[j]; if(!vis[t]&&d[t]>e[t][p]) d[t]=e[t][p]; } } //更新最小minweight/sum sum=0; for(i=1;i<=m;i++) sum+=w[s[i]]; double tt=minweight*1.0/sum; if(tt<rat) { rat=tt; for(i=1;i<=m;i++) ans[i]=s[i]; } } void dfs(int cnt,int p) { if(cnt==m+1) { prim(); return; } if(n-p<m-cnt) return; for(int i=p;i<=n;i++) { s[cnt]=i; dfs(cnt+1,i+1); } } int main() { int i,j; while(scanf("%d%d",&n,&m)&&(n||m)) { rat=inf; for(i=1;i<=n;i++) scanf("%d",&w[i]); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) scanf("%d",&e[i][j]); } dfs(1,1); for(i=1;i<m;i++) printf("%d ",ans[i]); printf("%d\n",ans[m]); } return 0; }
hdu2489 Minimal Ratio Tree,布布扣,bubuko.com
原文:http://blog.csdn.net/u011032846/article/details/21043263