Total Submission(s): 4566 Accepted Submission(s): 1448
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.
![](https://i-blog.csdnimg.cn/blog_migrate/2441ec4ba80861555b4cbcb65e2a0b61.jpeg)
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.
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.
![](https://i-blog.csdnimg.cn/blog_migrate/afed5416ad0a296b88ea8277ebc803fd.jpeg)
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<stdio.h> #include<bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; int n,m; int res[18]; int vis[18]; int maps[103][103]; int a[103]; int pre[18]; int t[103]; double res_rating; struct data { int x,y; int cost; bool operator<(const data &a)const { return cost<a.cost; } } p[1003]; void init() { for(int i=1; i<=n; i++) pre[i]=i; } int Find(int x) { if(x!=pre[x])return pre[x]=Find(pre[x]); return x; } double calculate() { init(); int tmp=0; double point=0; for(int i=1; i<=n; i++) { if(vis[i]) point+=a[i],t[++tmp]=i; } //printf("%d\n",tmp); int mm=0; for(int i=1; i<=tmp; i++) { for(int j=1; j<=tmp; j++) { p[++mm].x=t[i]; p[mm].y=t[j]; p[mm].cost=maps[t[i]][t[j]]; } } sort(p+1,p+1+mm); double side=0; for(int i=1; i<=mm; i++) { int X=Find(p[i].x); int Y=Find(p[i].y); if(X!=Y) { pre[X]=Y; side+=p[i].cost; } } return side/point; } void dfs(int u,int v) { if(u>n+1) return; if(v>m) return; if(u==n+1&&v==m) { double t=calculate(); if(t<res_rating) { //printf("%f\n",t); res_rating=t; memcpy(res,vis,sizeof(vis)); } } vis[u]=1; dfs(u+1,v+1); vis[u]=0; dfs(u+1,v); return; } int main() { while(scanf("%d%d",&n,&m),n,m) { memset(vis,0,sizeof(vis)); memset(res,0,sizeof(res)); res_rating=inf; for(int i=1; i<=n; i++) scanf("%d",&a[i]); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) scanf("%d",&maps[i][j]); } dfs(1,0); int flag=0; for(int i=1; i<=n; i++) { if(res[i]&&flag) printf(" %d",i); else if(res[i]) { flag=1; printf("%d",i); } } printf("\n"); } }