Minimal Ratio Tree
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2841 Accepted Submission(s): 844
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<stdio.h> const int N = 20; const int inf = 9999999; int nodew[N],map[N][N],n,m; int prim(int sta,int s) { int ins[N]={0},node[N],ts,mint,k=m,sum; k--; ins[s]=1; sum=0; for(int i=0;i<=n;i++) node[i]=inf; node[s]=0; while(k) { mint=inf; for(int i=0;i<n;i++) if(!ins[i]&&((1<<i)&sta)) { if(node[i]>map[s][i]) node[i]=map[s][i]; if(node[i]<mint) mint=node[i],ts=i; } if(mint!=inf) { s=ts; sum+=mint; ins[s]=1; k--; } else break; } if(k) return -1; else return sum; } int main() { int sum_e=inf,sta; double sum_n; while(scanf("%d%d",&n,&m)>0&&n+m!=0) { for(int i=0;i<n;i++) scanf("%d",&nodew[i]); for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&map[i][j]); sum_e=inf; sum_n=1; for(int s=1;s<(1<<n);s++) { int k=0,id,tsum_e; double tsum_n=0; for(int i=0;i<n;i++) if(s&(1<<i)) tsum_n+=nodew[i],k++,id=i; if(k!=m)continue; tsum_e=prim(s,id); if(tsum_e!=-1) if(tsum_e/tsum_n<sum_e/sum_n) sum_e=tsum_e,sum_n=tsum_n,sta=s; } int i; for(i=0; i<n; i++) if((1<<i)&sta) { printf("%d",i+1); break; } for(i++ ; i<n; i++) if((1<<i)&sta) printf(" %d",i+1); printf("\n"); } }