Minimal Ratio Tree

Minimal Ratio Tree

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 <iostream>
#include <cstring>
#include <fstream>
using namespace std;


int n,m;
int node[20],edge[20][20];
int a[20];
int tmin[20];
int minValue[2] ;  //0 分子  1 分母

int prim(){
	int i,j;
	int visE[20][20];
	int visN[20],p1,p2;
	int minE ;
	int sumNum = 0;
	memset(visE,0,sizeof(visE));
	memset(visN, 0, sizeof(visN));
	int nodeN = 1;
	visN[a[0]] = 1;
	while(1){
		minE = -1;
		for(i=0 ; i<m ; i++){
			for(j= i+1 ; j<m ;j++) if(visE[a[i]][a[j]] == 0 &&
				((visN[a[i]]!=0 && visN[a[j]]==0) || (visN[a[i]]==0 && visN[a[j]]!=0)) //点必须在已找到的点种扩展
				){
				if(minE == -1 || minE > edge[a[i]][a[j]]){
					minE = edge[a[i]][a[j]];
					p1 = a[i];
					p2 = a[j];
				}
			}
		}
		visE[p1][p2] = 1;
		visN[p1] = 1;
		visN[p2] = 1;
		sumNum += minE;
		nodeN++;
		if(nodeN == m)
			break;
	}
	return sumNum;
}

void zuhe(int _i,int cur)
{
	int i;
	if(cur==m)
	{
		// 处理
		int sumN=0,sumE=0;
		for(i=0 ; i<m ; i++){
			sumN += node[a[i]];
		}
		sumE = prim();
		if(minValue[0] == -1 || minValue[0]*sumN > sumE*minValue[1]){
			minValue[0] = sumE;
			minValue[1] = sumN;
			memcpy(tmin, a, sizeof(a));
		}
		return;
	}

	for(i=_i; i<n ; i++){
		a[cur] = i;
		zuhe(i+1,cur+1);
	}
}

int main(){

	int i,j;
	
	while(1)
	{
		cin>>n>>m;
		if(n == 0 && m == 0)
			break;

		for(i=0; i<n; i++)
		{
			cin>>node[i];  //节点的权值
		} //for
		for(i=0; i<n; i++)
		{
			for(j=0; j<n; j++)
			{
				cin>>edge[i][j];  // 边的权值
			} //for
		} //for

		minValue[0] = -1;
		memset(tmin , -1 ,sizeof(tmin));

		zuhe(0,0);

		//cout<<"ans:";
		cout<<tmin[0]+1;
		for(i=1 ; i<m ; i++){
			cout<<" "<<tmin[i]+1;
		}
		cout<<endl;


	}//while
	return 0;
}
 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值