hdu2489-DFS+最小生成树

题意:
      给你n个点,和任意两点的距离,让你在这N个点中找到一个有m个点并且ratio最小的树.
                        ratio = sum(edge) / sum(node)

思路: N <= 15 直接DFS暴力枚举出 m个点,然后再这m个点中跑一边最小生成树,这m个点的sum(node) 可以直接加出来,而 sum(edge) 就是最小生数的值,然后求出ratio更新最小,记录答案. 


#include<stdio.h>
#include<string.h>
#include<algorithm>

#define N 20
#define inf 100000000;

using namespace std;

typedef struct
{
   int a ,b ,c;
}NODE;

bool camp(NODE a ,NODE b)
{
   return a.c < b.c;
}

NODE node[N*N];
int map[N][N] ,weight[N];
int ans_num[N] ,now[N] ,n ,nn; 
int mer[N];
double now_min;

int finds(int x)
{
   if(x == mer[x]) return x;
   return mer[x] = finds(mer[x]);
}


void DFS(int s ,int t)
{
   if(t == n + 1)
   {
      int tmp = 0 ,sum1 = 0 ,sum2 = 0 ,mm = 0;
      for(int i = 1 ;i <= n ;i ++)
      {
         sum1 += weight[now[i]];
         for(int j = i + 1 ;j <= n ;j ++)
         {
            node[++tmp].a = now[i];
            node[tmp].b = now[j];
            node[tmp].c = map[now[i]][now[j]];
            if(mm < now[i]) mm = now[i];
            if(mm < now[j]) mm = now[j];
         }
      }
      sort(node + 1 ,node + tmp + 1 ,camp);
      for(int i = 1 ;i <= mm ;i ++)
      mer[i] = i;
      mm = 0;
      for(int i = 1 ;i <= tmp ;i ++)
      {
         int x = finds(node[i].a);
         int y = finds(node[i].b);
         if(x == y) continue;         
         mer[x] = y;
         sum2 += node[i].c; 
         if(++mm == n - 1) break;
      }
      //printf("%d %d %d %d
" ,sum1 ,sum2 ,now[1] ,now[2]);
      double nowm = sum2 * 1.0 / sum1;
      if(nowm < now_min)
      {
         now_min = nowm;
         for(int i = 1 ;i <= n ;i ++)
         ans_num[i] = now[i];
      }
      return ;
   }
   
   for(int i = s + 1 ;i <= nn ;i ++)
   {
      now[t] = i;
      DFS(i ,t + 1);
   }
}

int main ()
{
   int i;
   while(scanf("%d %d" ,&nn ,&n) && n + nn)
   {
      for(i = 1 ;i <= nn ;i ++)
      scanf("%d" ,&weight[i]);
      for(i = 1 ;i <= nn ;i ++)
      for(int j = 1 ;j <= nn ;j ++)
      scanf("%d" ,&map[i][j]);
      now_min = inf;
      DFS(0 ,1);
      for(i = 1 ;i < n ;i ++)
      printf("%d " ,ans_num[i]);
      printf("%d
" ,ans_num[i]);
   }
   return 0;
}

       





原文地址:https://www.cnblogs.com/csnd/p/12063279.html