poj_3925 Minimal Ratio Tree

Minimal Ratio Tree

Time Limit: 1000MS

Memory Limit: 65536K

Total Submissions: 836

Accepted: 304

题目链接:http://poj.org/problem?id=3925

Description

For a tree, which nodes and edges are all weighted, the ratio of it iscalculated according to the following equation.


Given a complete graph of n nodes with all nodes and edges weighted, your taskis to find a tree, which is a sub-graph of the original graph, with m nodes andwhose 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 casecontains two integers n (2<=n<=15) and m (2<=m<=n), which standsfor the number of nodes in the graph and the number of nodes in the minimalratio tree. Two zeros end the input. The next line contains n numbers whichstand for the weight of each node. The following n lines contain a diagonallysymmetrical n×n connectivity matrix with each element shows the weight of theedge 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 ofthe matrix) are integers and in the range of [1, 100].

The figure below illustrates the first test case in sample input. Node 1 andNode 3 form the minimal ratio tree.

Output

For each test case output oneline contains a sequence of the m nodes which constructs the minimal ratiotree. Nodes should be arranged in ascending order. If there are several suchsequences, 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 arenumbered 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

Beijing 2008

 

题意:

         给你一个完全图,求其中m个点中的radio最小radio=(每条边的权值之和)/(每个点的权值之和)

解题思路:

         我是先求出n个点中m个点的每一种组合,在每一种组合中的点,在用prim算法求这些点的最小生成树的值,再计算该组合的radio值,并保存最小的radio对应的点,最后输出每个点

代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#define maxn 100
#define VALUE 0xffffff
using namespace std;

struct edgeRadio
{
	int member[maxn];
	int t;
};

int noteweight[maxn];//点权
int edgeweight[maxn][maxn];//边权
edgeRadio edgeradio;
int n,m;
int visited[maxn];
int minCost[maxn];
double minValue;
edgeRadio minEdge;
//prim算法求最小值
int prim()
{
	int i;
	int res=0;
	for(i=0;i<=n;i++)
	{
		visited[i]=0;
		minCost[i]=VALUE;
	}
	minCost[edgeradio.member[0]]=0;
	while(true)
	{
		int t=-1;
		for(i=1;i<=m;i++)
		{
			if(visited[edgeradio.member[i-1]]==0 && (t==-1 || minCost[edgeradio.member[i-1]]<minCost[t]))
				t=edgeradio.member[i-1];
		}
		if(t==-1)
			break;
		visited[t]=1;
		res+=minCost[t];
		for(i=1;i<=m;i++)
		{
			if(minCost[edgeradio.member[i-1]]>edgeweight[edgeradio.member[i-1]][t] && edgeweight[edgeradio.member[i-1]][t]!=0)
			{
				minCost[edgeradio.member[i-1]]=edgeweight[edgeradio.member[i-1]][t];
			}
		}
	}
	return res;
}

//求radio
double getRadio()
{
	int num=0;
	int res=prim();
	
	for(int i=1;i<=m;i++)
	{
		num+=noteweight[edgeradio.member[i-1]];
	}
	return res*1.0/num;
}

//递归求每一种组合
void getNum(int t,int p)
{
	if(t==0)
	{
		double res = getRadio();
		if(minValue>res)
		{
			minValue=res;
			minEdge=edgeradio;
		}

		return ;
	}
	else
	{
		for(int i=p;i<=n;i++)
		{
			edgeradio.member[edgeradio.t]=i;
			edgeradio.t++;
			getNum(t-1,p+1);
			edgeradio.t--;
			p++;
		}
	}
}


int main()
{

    int i,j;

    while(true)
    {
        scanf("%d%d",&n,&m);
        minValue=VALUE;
        if(n==0 && m==0)
            break;
		memset(edgeweight,0,sizeof(edgeweight));

        for(i=1;i<=n;i++)
        {
            scanf("%d",¬eweight[i]);
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                scanf("%d",&edgeweight[i][j]);
            }
        }
		getNum(m,1);
		for(i=0;i<minEdge.t-1;i++)
		{
			printf("%d ",minEdge.member[i]);
		}
		printf("%d\n",minEdge.member[i]);

    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯的世界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值