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("");
        }
    }
     
  • 相关阅读:
    基于摸板匹配的目標跟蹤算法
    spoj 2713 Can you answer these queries IV
    zoj 3633 Alice's present
    hdu 3642 Get The Treasury
    poj 1195 Mobile phones
    poj 2760 End of Windless Days
    zoj 3540 Adding New Machine
    spoj 1716 Can you answer these queries III
    spoj 1043 Can you answer these queries I
    spoj 2916 Can you answer these queries V
  • 原文地址:https://www.cnblogs.com/mfys/p/7242163.html
Copyright © 2011-2022 走看看