zoukankan      html  css  js  c++  java
  • 最小生成树 状压+prim hdu2489

    Minimal Ratio TreeTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 4462    Accepted Submission(s): 1411


    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
     
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    const int inf=1008611;
    using namespace std;
    int par[22],n,m,va[22],mp[22][22],num[22];
    double rap;
    bool Ju(int k)
    {
        int tc=0;
        while(k)
        {
            if(k&1)
            {
                k|=1;
                ++tc;
            }
            k>>=1;
        }
        return tc==m;
    }
    void slove(int zt)
    {
        double sv=0,se=0;
        vector<int>pt;
        int mark,low[22];
        bool vis[22];
        for(int i=0; i<n; ++i)
            if((1<<i)&zt)
            {
                vis[i]=0;
                low[i]=inf;
                sv+=va[i];
                pt.push_back(i);
            }
        mark=pt[0];
        vis[mark]=1;
        for(int i=1; i<m; ++i)
        {
            int u=mark,minn=inf;
            for(int j=0; j<m; ++j)
                if(low[pt[j]]>mp[u][pt[j]]) low[pt[j]]=mp[u][pt[j]];
            for(int j=0; j<m; ++j)
                if(minn>low[pt[j]]&&!vis[pt[j]])
                {
                    minn=low[pt[j]];
                    mark=pt[j];
                }
            se+=low[mark];
            vis[mark]=1;
        }
        double rs=se*1.0/sv;
        if(rs<rap)
        {
            for(int i=0; i<m; ++i)
                num[i]=pt[i];
                rap=rs;
        }
        else if(rs==rap)
        {
            bool rig=0;
            for(int i=0; i<m; ++i)
            {
                if(num[i]>pt[i])
                {
                    rig=1;
                    break;
                }
                else if(num[i]<pt[i]) break;
            }
            if(rig)
            {
                for(int i=0; i<m; ++i)
                    num[i]=pt[i];
            }
        }
        return ;
    }
    int main()
    {
        while(scanf("%d%d",&n,&m),n||m)
        {
            rap=inf;
            for(int i=0; i<n; ++i) scanf("%d",va+i);
            for(int i=0; i<n; ++i)
                for(int j=0; j<n; ++j)
                {
                    scanf("%d",&mp[i][j]);
                    if(i==j) mp[i][j]=inf;
                }
            for(int i=0; i<(1<<n); ++i)
                if(Ju(i)) slove(i);
            for(int i=0; i<m; ++i)
                if(i) printf(" %d",num[i]+1);
                else printf("%d",num[i]+1);
            puts("");
        }
    }
     
  • 相关阅读:
    select和epoll的区别
    Epoll导致的selector空轮询
    2.集合框架中的泛型有什么优点?
    java的语法基础(二)
    17-文本属性和字体属性
    15-浮动
    16-margin的用法
    14-块级元素和行内元素
    12-简单认识下margin
    day15 什么是递归/递归与回溯
  • 原文地址:https://www.cnblogs.com/mfys/p/7242163.html
Copyright © 2011-2022 走看看