• HDU 2489 Minimal Ratio Tree (dfs+Prim最小生成树)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2489


    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

    题意:

    给出n个点。要从中选出m个点。要求选出的这m个点的全部边的边权值/点权值要最小!

    并要输出所选的这m个点,假设有多种选择方法,那么就输出第一个点小的方案,假设第一个点同样就输出第二个点小的,一次类推!


    PS:

    因为这题的n比較小,仅仅有15。所以能够先dfs枚举出所选择的点。然后在用最小生成树Prim算出最小的边权值的和。


    代码例如以下:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    #define INF 1e18;
    const double eps = 1e-9;
    const int maxn = 17;
    int n, m;
    int e_val[maxn][maxn];
    int node[maxn];
    int ansn[maxn];//记录终于选得是哪些点
    int tt[maxn];//记录中间过程选得是哪些点
    int vis[maxn];
    int low[maxn];
    double minn;
    int Prim(int s)
    {
        int sum=0;
        memset(vis,0,sizeof(vis));
        for(int i = 1; i <= m; i++)
        {
            low[tt[i]] = e_val[s][tt[i]];
        }
        vis[s] = 1;
        low[s] = 0;
        int pos = s;
        for(int i = 1; i < m; i++)
        {
            int min_t = INF;
            for(int j = 1; j <= m; j++)
            {
                if(!vis[tt[j]] && min_t > low[tt[j]])
                {
                    min_t = low[tt[j]];
                    pos = tt[j];
                }
            }
            vis[pos] = 1;
            sum += min_t;
            for(int j = 1; j <= m; j++)
            {
                if(!vis[tt[j]] && e_val[pos][tt[j]] < low[tt[j]])
                    low[tt[j]]=e_val[pos][tt[j]];
            }
        }
        return sum;
    }
    void DFS(int n_pre, int k)
    {
        if(k == m)
        {
            double n_sum = 0;
            for(int i = 1; i <= m ; i++)
            {
                n_sum+=node[tt[i]];
            }
            double e_ans = 0;
            e_ans = Prim(tt[1]);
            double ans = e_ans/(n_sum*1.0);
            //if(ans < minn)
            if(ans - minn < -(eps))
            {
                minn = ans;
                for(int i = 1; i <= m; i++)
                {
                    ansn[i] = tt[i];
                }
            }
            return ;
        }
        for(int i = n_pre+1; i <= n; i++)
        {
            tt[k+1] = i;
            DFS(i,k+1);
        }
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            if(n==0 && m==0)
                break;
            minn = INF;
            for(int i = 1; i <= n; i++)
            {
                scanf("%d",&node[i]);
            }
            for(int i = 1; i <= n; i++)
            {
                for(int j = 1; j <= n; j++)
                {
                    scanf("%d",&e_val[i][j]);
                }
            }
            for(int i = 1; i <= n; i++)
            {
                tt[1] = i;
                DFS(i, 1);
            }
            for(int i = 1; i < m; i++)
            {
                printf("%d ",ansn[i]);
            }
            printf("%d
    ",ansn[m]);
        }
        return 0;
    }
    


  • 相关阅读:
    【转】Redis主从复制简介
    Redis配置文件详解
    Redis在Windows环境下搭建
    Redis桌面管理工具 RedisDesktopManager
    Redis服务停止报错解决方案[NOAUTH Authentication required]
    Redis启动警告错误解决
    修改tcp内核参数:somaxconn
    CentOS6.8安装Redis3.2.5
    Github之协同开发
    自定义实现栈的功能
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/6937041.html
Copyright © 2020-2023  润新知