POJ3925 Minimal Ratio Tree

Minimal Ratio Tree
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 1071 Accepted: 389

Description

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

Ratio=\frac{\sum{edgeweight}}{\sum{nodeweight}}


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


先用回溯找到所有的组合,在用最小生成树,注意返回的值是边权/点权

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
const double INF = 1e10;
const int maxn = 25;
vector<vector<int> > g;
double mat[maxn][maxn],NODE[maxn],ratio[maxn];
bool vis[maxn];
int n,m;
void input(){
	g.clear();
	for(int i = 1; i <= n; i++) scanf("%lf",&NODE[i]);
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++)
			scanf("%lf",&mat[i][j]);
}
void cc(vector<int> &k,int c){
	if(k.size()==m){
		g.push_back(k);
		return;
	}
	for(int i = c; i <= n; i++){
		k.push_back(i);	
		cc(k,i+1);
		k.pop_back();
	}
}
double prim(vector<int> &node){
	int v = -1;
	double mincost[maxn],ans = 0;
	for(int i = 0; i < node.size(); i++){
		mincost[node[i]] = INF;
		vis[node[i]] = 0;
	}
	mincost[node[0]] = 0;
	double res = 0;
	for(int i = 0; i < node.size(); i++){
		int v = -1;
		for(int j = 0; j < node.size(); j++)
			if(!vis[node[j]]){	
				if(v == -1) v = node[j];
				else if(mincost[node[j]]<mincost[v]) v = node[j];
			}
		if(v == -1) break;
		vis[v] = 1;
		ans+=mincost[v];
		for(int j = 0; j < node.size(); j++){
			if(fabs(mat[v][node[j]])>1e-8){
				if(!vis[node[j]]){
					int x = node[j];
					mincost[x] = min(mincost[x],mat[v][node[j]]);
				}
			}
		}
	}
	double SN = 0;
	for(int i = 0; i < node.size(); i++){
		SN += NODE[node[i]];
	}
	return ans/SN;
}
void solve(){
	vector<int> node;
	cc(node,1);
	node.clear();
	double ans = INF;
	for(int i = 0; i < g.size(); i++){
		double tmp = prim(g[i]);
		if(ans > tmp){
			ans = tmp;
			node = g[i];
		}
	}
	sort(node.begin(),node.end());
	cout<<node[0];
	for(int i = 1; i < node.size(); i++)
		cout<<" "<<node[i];
	cout<<endl;
}
int main(){
	while(~scanf("%d%d",&n,&m)&&n+m){
		input();
		solve();	
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值