码迷,mamicode.com
首页 > 其他好文 > 详细

HDU ACM 2489 Minimal Ratio Tree

时间:2015-05-29 14:05:07      阅读:102      评论:0      收藏:0      [点我收藏+]

标签:acm   c++   杭电   算法   编程   

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


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个顶点的最小生成树,选出一个比率最小的即可Prim算法。注意至少要深搜1-——n-m+1个结点,才能确保遍历所有组合
#include<iostream>
#include<string.h>
using namespace std;
const int INF=0x1f1f1f1f;


int edge[20][20];
int node[20];
bool flag[20];
bool f1[20];
double res;
int dfs_cnt;
bool arr[20];
int n,m;
int mst()
{
    int ret=0;
    int low[20]={0};
    int sta;
    for(int i=1;i<=n;i++)
    {
        if(f1[i])
        {
            sta=i;
            break;
        }
    }
    low[sta]=0;
    flag[sta]=1;
    for(int i=1;i<=n;i++)
    {
        if(f1[i])
        {
            low[i]=edge[sta][i];
        }
    }
    for(int i=1;i<m;i++)
    {
        int Min=INF;
        int loc;
        for(int j=1;j<=n;j++)
        {
            if(f1[j]&&!flag[j]&&low[j]<Min)
            {
                Min=low[j];
                loc=j;
            }
        }
        flag[loc]=1;
        ret+=low[loc];
        for(int j=1;j<=n;j++)
        {
            if(f1[j]&&!flag[j])
            {
                if(edge[loc][j]<low[j])
                {
                    low[j]=edge[loc][j];
                }
            }
        }
    }
    return ret;
}

void dfs(int v)
{
    f1[v]=1;
    dfs_cnt++;
    if(dfs_cnt==m)
    {
        memset(flag,0,sizeof(flag));
        int r=mst();
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            if(f1[i])
            {
                sum+=node[i];
            }
        }
        double ans=double(r)/double(sum);
        if(ans-res<-(1e-9))
        {
          memcpy(arr,f1,sizeof(f1));
          res=ans;
        }
        f1[v]=0;
        dfs_cnt--;
        return ;
    }
    for(int i=v+1;i<=n;i++)
    {
        dfs(i);
    }
    f1[v]=0;
    dfs_cnt--;

}
int main()
{
    while(cin>>n>>m,n+m)
    {
        for(int i=1;i<=n;i++)
            cin>>node[i];
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
                cin>>edge[i][j];
        }
        res=double (INF);
        for(int i=1;i<=n-m+1;i++)
        {
            memset(f1,0,sizeof(f1));
            dfs_cnt=0;
            dfs(i);
        }
        int fir=1;
        for(int i=1;i<=n;i++)
        {
            if(arr[i])
            {
                if(fir)
                {
                    fir=0;
                    cout<<i;
                }
                else
                    cout<<" "<<i;
            }
        }
        cout<<endl;
    }
    return 0;
}

HDU ACM 2489 Minimal Ratio Tree

标签:acm   c++   杭电   算法   编程   

原文地址:http://blog.csdn.net/lsgqjh/article/details/46228691

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!