最小生成树 状压+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("");
    }
}
 
posted @ 2017-07-26 21:35  Billyshuai  阅读(117)  评论(0编辑  收藏  举报