zoukankan      html  css  js  c++  java
  • HDU 2489 Minimal Ratio Tree(暴力+最小生成树)(2008 Asia Regional Beijing)

    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 .

    题目大意:给n个点,一个完全图,要求你选出m个点和m-1条边组成一棵树,其中sum(边权)/sum(点权)最小,并且字典序最小,输出这m个点。

    思路:大水题,n个选m个,$C_{n}^{m}$最大也不到1W,最小生成树算法也才$O(n^2)$,果断暴力。暴力枚举选和不选,然后用最小生成树求sum(边权),逐个比较即可。

    PS:太久没写最小生成树结果混入了最短路的东西结果WA了>_<

    代码(15MS):

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 using namespace std;
     5 
     6 const int MAXN = 18;
     7 const int INF = 0x3fff3fff;
     8 
     9 int mat[MAXN][MAXN];
    10 int weight[MAXN];
    11 int n, m;
    12 bool use[MAXN], vis[MAXN];
    13 int dis[MAXN];
    14 
    15 int prim(int st) {
    16     memset(vis, 0, sizeof(vis));
    17     vis[st] = true;
    18     for(int i = 1; i <= n; ++i) dis[i] = mat[st][i];
    19     int ret = 0;
    20     for(int cnt = 1; cnt < m; ++cnt) {
    21         int u, min_dis = INF;
    22         for(int i = 1; i <= n; ++i)
    23             if(use[i] && !vis[i] && dis[i] < min_dis) u = i, min_dis = dis[i];
    24         ret += min_dis;
    25         vis[u] = true;
    26         for(int i = 1; i <= n; ++i)
    27             if(use[i] && !vis[i] && dis[i] > mat[u][i]) dis[i] = mat[u][i];
    28     }
    29     return ret;
    30 }
    31 
    32 bool ans[MAXN];
    33 int ans_pw, ans_ew;
    34 
    35 void dfs(int dep, int cnt, int sum_pw) {
    36     if(cnt == m) {
    37         int sum_ew = prim(dep - 1);
    38         if(ans_ew == INF || ans_ew * sum_pw > ans_pw * sum_ew) {//ans_ew/ans_pw > sum_ew/sum_pw
    39             for(int i = 1; i <= n; ++i) ans[i] = use[i];
    40             ans_ew = sum_ew; ans_pw = sum_pw;
    41         }
    42         return ;
    43     }
    44     if(dep == n + 1) return ;
    45     use[dep] = true;
    46     dfs(dep + 1, cnt + 1, sum_pw + weight[dep]);
    47     use[dep] = false;
    48     dfs(dep + 1, cnt, sum_pw);
    49 }
    50 
    51 int main() {
    52     while(scanf("%d%d", &n, &m) != EOF) {
    53         if(n == 0 && m == 0) break;
    54         for(int i = 1; i <= n; ++i) scanf("%d", &weight[i]);
    55         for(int i = 1; i <= n; ++i) {
    56             for(int j = 1; j <= n; ++j) scanf("%d", &mat[i][j]);
    57         }
    58         ans_ew = INF; ans_pw = 1;
    59         dfs(1, 0, 0);
    60         bool flag = false;
    61         for(int i = 1; i <= n; ++i) {
    62             if(!ans[i]) continue;
    63             if(flag) printf(" ");
    64             else flag = true;
    65             printf("%d", i);
    66         }
    67         printf("
    ");
    68     }
    69 }
    View Code
  • 相关阅读:
    HDOJ 1588 Gauss Fibonacci
    HDOJ 1494 跑跑卡丁车
    初识Linux
    大数据教程
    80后上班族
    人际交往,七种心态最惹人讨厌
    商人初步
    分页存储过程
    父母生日
    dephi小技巧
  • 原文地址:https://www.cnblogs.com/oyking/p/3258425.html
Copyright © 2011-2022 走看看