HDU 2489 DFS枚举所有组合+最小生成树
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2489
题目大意:给出N个点,每个点都有点权值,再给出整张图的边权值[1,100](即每条边的权值都大于0),然后在限制的M个点数中找出最小的ratio,。
思路:DFS枚举所有点的组合情况,用枚举出来的点建立一张子图。然后再用最小生成树求出子图最小边权值的和。
代码:
1 #include<iostream> 2 using namespace std; 3 #define maxn 22 4 int f[maxn][maxn],g[maxn][maxn]; 5 int vis[maxn],ans[maxn],dis[maxn],m,node[maxn],w[maxn],n; 6 double sum; 7 double prim() 8 { 9 int i,j; 10 for(i=1;i<=m;i++) 11 { 12 dis[i]=f[1][i]; 13 vis[i]=0; 14 } 15 vis[1]=1; 16 double sum=0; 17 for(i=2;i<=m;i++) 18 { 19 int Min=0x3f3f3f3f,pos; 20 for(j=1;j<=m;j++) 21 if(Min>dis[j]&&!vis[j]) 22 Min=dis[j],pos=j; 23 sum+=Min; 24 vis[pos]=1; 25 for(j=1;j<=m;j++) 26 { 27 if(dis[j]>f[pos][j]&&!vis[j]) 28 dis[j]=f[pos][j]; 29 } 30 } 31 return sum; 32 } 33 void dfs(int u,int cnt) 34 { 35 int i,j; 36 node[cnt]=u; 37 if(cnt>=m) 38 { 39 for(i=1;i<=m;i++) 40 for(j=1;j<=m;j++) 41 f[i][j]=g[node[i]][node[j]]; 42 double sum_edge=prim(); 43 double sum_point=0; 44 for(i=1;i<=m;i++) 45 sum_point+=w[node[i]]; 46 double ret=sum_edge/sum_point; 47 if(sum>ret) 48 { 49 sum=ret; 50 for(i=1;i<=m;i++) 51 ans[i]=node[i]; 52 } 53 return ; 54 } 55 for(i=u+1;i<=n;i++) 56 dfs(i,cnt+1); 57 } 58 int main() 59 { 60 int i,j; 61 while(scanf("%d %d",&n,&m),n||m) 62 { 63 for(i=1;i<=n;i++) 64 scanf("%d",&w[i]); 65 for(i=1;i<=n;i++) 66 for(j=1;j<=n;j++) 67 scanf("%d",&g[i][j]); 68 sum=0x3f3f3f3f; 69 for(i=1;i<=n;i++) 70 dfs(i,1); 71 for(i=1;i<=m;i++) 72 { 73 if(i!=m) 74 cout<<ans[i]<<' '; 75 else 76 cout<<ans[i]<<endl; 77 } 78 } 79 return 0; 80 }
posted on 2013-07-29 11:38 acoderworld 阅读(125) 评论(0) 收藏 举报