Minimal Ratio Tree prime()&&枚举点

Problem Description
For a tree, which nodes and edges are all weighted, the ratio of it is calculated according to the following equation.




Given a complete graph of n nodes with all nodes and edges weighted, your task is to find a tree, which is a sub-graph of the original graph, with m nodes and whose ratio is the smallest among all the trees of m nodes in the graph.
 

 

Input
Input contains multiple test cases. The first line of each test case contains two integers n (2<=n<=15) and m (2<=m<=n), which stands for the number of nodes in the graph and the number of nodes in the minimal ratio tree. Two zeros end the input. The next line contains n numbers which stand for the weight of each node. The following n lines contain a diagonally symmetrical n×n connectivity matrix with each element shows the weight of the edge connecting one node with another. Of course, the diagonal will be all 0, since there is no edge connecting a node with itself.



All the weights of both nodes and edges (except for the ones on the diagonal of the matrix) are integers and in the range of [1, 100].

The figure below illustrates the first test case in sample input. Node 1 and Node 3 form the minimal ratio tree. 
 

 

Output
For each test case output one line contains a sequence of the m nodes which constructs the minimal ratio tree. Nodes should be arranged in ascending order. If there are several such sequences, pick the one which has the smallest node number; if there's a tie, look at the second smallest node number, etc. Please note that the nodes are numbered from 1 .
 

 

Sample Input
3 2
30 20 10
0 6 2
6 0 3
2 3 0
2 2
1 1
0 2
2 0
0 0
 

 

Sample Output
1 3
1 2
***************************************************************************************************************************
从n个点抽出m个点,组成最小生成树
***************************************************************************************************************************
  1 #include<iostream>
  2 #include<string>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<cstdio>
  6 using namespace std;
  7 int vis1[1001],vis2[1001],ans[1001];
  8 double e[1001][1001],p[1001],dis[1001],minRatio;
  9 int n,m,i,j;
 10 double prime()//求最小生成树
 11 {
 12     int u;
 13     memset(vis1,0,sizeof(vis1));
 14     int it,jt;
 15     u=0;
 16     while(!vis2[u]&&u<=n)u++;
 17     vis1[u]=1;
 18     double psum=0.0,esum=0.0;
 19     for(it=1;it<=n;it++)
 20     {
 21         if(vis2[it])
 22         {
 23             dis[it]=e[u][it];
 24             psum+=p[it];
 25         }
 26     }
 27     for(it=1;it<m;it++)
 28     {
 29         u=-1;
 30         for(jt=1;jt<=n;jt++)
 31         {
 32             if(vis2[jt]&&!vis1[jt])
 33                 if(u==-1||dis[jt]<dis[u])
 34                 {
 35                    u=jt;
 36                 }
 37 
 38         }
 39         esum+=dis[u];
 40         vis1[u]=1;
 41         for(jt=1;jt<=n;jt++)
 42         {
 43             if(!vis1[jt]&&vis2[jt])
 44               if(dis[jt]>e[u][jt])
 45                 dis[jt]=e[u][jt];
 46         }
 47     }
 48     return esum/psum;
 49 }
 50 void dfs(int u,int num)//枚举
 51 {
 52     if(num>m)return;
 53     if(u==n+1)
 54     {
 55         if(num!=m)return;
 56         double t=prime();
 57         //cout<<"T:: "<<t<<endl;
 58         if(t<minRatio)
 59         {
 60                 minRatio=t;
 61               memcpy(ans,vis2,sizeof(vis2));//记录
 62         }
 63         return;
 64     }
 65     vis2[u]=1;
 66     dfs(u+1,num+1);
 67     vis2[u]=0;
 68     dfs(u+1,num);
 69 
 70 }
 71 int main()
 72 {
 73     while(scanf("%d %d",&n,&m)!=EOF)
 74     {
 75         if(n==0&&m==0)
 76             break;
 77         for(i=1;i<=n;i++)
 78         {
 79             scanf("%lf",&p[i]);
 80             //printf("p::%lf\n",p[i]);
 81         }
 82         for(i=1;i<=n;i++)
 83          for(j=1;j<=n;j++)
 84           {
 85             scanf("%lf",&e[i][j]);
 86           }
 87           minRatio=10000000.0;
 88           memset(vis2,0,sizeof(vis2));
 89           //memset(ans,0,sizeof(ans));
 90           dfs(1,0);
 91         bool gs=0;
 92           for(i=1;i<=n;i++)
 93           {
 94               if(ans[i])
 95                {
 96                    if(gs==0)
 97                    {
 98                        printf("%d",i);
 99                        gs=1;
100                     }
101                     else
102                     {
103                         printf(" %d",i);
104                     }
105                }
106           }
107          puts("");
108     }
109     return 0;
110 }
View Code

 

转载于:https://www.cnblogs.com/sdau--codeants/p/3402073.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值