zoukankan      html  css  js  c++  java
  • hdu 2489 Minimal Ratio Tree

    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
     
    Source
     
     
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #define inf 0x3f3f3f3f
      5 using namespace std;
      6 int n,m;
      7 int num[20];
      8 int map[20][20];
      9 int ans[20][20];
     10 int dis[20];
     11 bool mark[20];
     12 int DJ(int pm)
     13 {
     14     memset(dis,inf,sizeof(dis));
     15     memset(mark,false,sizeof(mark));
     16     for(int i=1;i<pm;i++)
     17     {
     18         dis[i]=ans[0][i];
     19     }
     20     mark[0]=true;
     21     int res=0;
     22     int temp;
     23     for(int i=1;i<pm;i++)
     24     {
     25         int Mi=inf;
     26         for(int j=0;j<pm;j++)
     27         {
     28             if(!mark[j] && dis[j]<Mi)
     29             {
     30                 Mi=dis[j];
     31                 temp=j;
     32             }
     33         }
     34         mark[temp]=true;
     35         res+=Mi;
     36         for(int j=0;j<pm;j++)
     37         {
     38            if(!mark[j] && dis[j]>ans[temp][j])
     39             {
     40                 dis[j]=ans[temp][j];
     41             }
     42         }
     43     }
     44     return res;
     45 }
     46 int main()
     47 {
     48     while(~scanf("%d%d",&n,&m))
     49     {
     50         if(n==0 && m==0)
     51         {
     52             break;
     53         }
     54         for(int i=0;i<n;i++)
     55         {
     56             scanf("%d",&num[i]);
     57         }
     58 
     59         for(int i=0;i<n;i++)
     60         {
     61             for(int j=0;j<n;j++)
     62             {
     63                 scanf("%d",&map[i][j]);
     64             }
     65         }
     66         double Minres=inf;
     67         int respos;
     68         for(int i=3;i<(1<<n);i++)
     69         {
     70             int nw=0;
     71             int len=0;
     72             int cnt=0;
     73             int res[20];
     74             memset(res,-1,sizeof(res));
     75             while(i>=(1<<len))
     76             {
     77                 if(i&(1<<len))
     78                 {
     79                     nw+=num[len];
     80                     res[cnt++]=len;
     81                 }
     82                 len++;
     83             }
     84             if(cnt!=m)
     85             {
     86                 continue;
     87             }
     88             memset(ans,inf,sizeof(ans));
     89             for(int j=0;j<cnt;j++)
     90             {
     91                 for(int k=j+1;k<cnt;k++)
     92                 {
     93                     ans[j][k]=map[res[j]][res[k]];
     94                     ans[k][j]=map[res[k]][res[j]];
     95                 }
     96             }
     97             int rr=DJ(cnt);
     98             if(rr*1.0/(nw*1.0)-Minres<-(1e-6))
     99             {
    100                 Minres=rr*1.0/(nw*1.0);
    101                 respos=i;
    102             }
    103         }
    104         bool ff=false;
    105         for(int i=0;i<n;i++)
    106         {
    107             if(respos&(1<<i))
    108             {
    109                 if(!ff)
    110                 {
    111                     ff=true;
    112                     printf("%d",i+1);
    113                 }
    114                 else
    115                 {
    116                     printf(" %d",i+1);
    117                 }
    118             }
    119         }
    120         printf("
    ");
    121     }
    122     return 0;
    123 }
    View Code
     
    数据量的允许,使用二进制压缩的方法,枚举各种可能,每次都求一次最小生成树;
    注意的地方是double 判<0( 小于0)使用高精度判断 例如判小于可以(a<b):a-b<-(1e-8)
    否则会出现WA的情况
  • 相关阅读:
    Jq操作表格
    最新web 2.0 配色 (一)
    Jqtable edit
    Jq公告渐隐弹出
    Jq模拟最大化最小化关闭
    JqtoggleClass
    Jq弹出公告
    jquery左右拉效果
    最新web 2.0 配色 (二)
    ZenCoding各个工具安装
  • 原文地址:https://www.cnblogs.com/ouyangduoduo/p/3320230.html
Copyright © 2011-2022 走看看