Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3899 Accepted Submission(s): 1196
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.
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.
#include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <math.h> using namespace std; const int N = 16; const int INF = 9999999999; int graph[N][N]; int weight[N]; int state[1<<N]; int a[N],result[N];; int n,m; int vis[N],low[N]; void input(){ for(int i=1;i<=n;i++) scanf("%d",&weight[i]); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ scanf("%d",&graph[i][j]); } } } bool check(int num){ int cnt =0; while(num){ if(num&1) cnt++; num = num>>1; } if(cnt==m) return true; return false; } void init(int &k){ for(int i=0;i<(1<<n);i++){ if(check(i)) state[k++]=i; } k--; } int prim(int n,int pos){ memset(vis,0,sizeof(vis)); for(int i=0;i<n;i++){ low[a[i]] = graph[pos][a[i]]; } vis[pos] = true; int cost = 0; for(int i=1;i<n;i++){ int Min = INF; for(int j=0;j<n;j++){ if(!vis[a[j]]&&low[a[j]]<Min){ pos = a[j]; Min = low[a[j]]; } } vis[pos] = true; cost +=Min; for(int j=0;j<n;j++){ if(!vis[a[j]]&&low[a[j]]>graph[pos][a[j]]) low[a[j]] = graph[pos][a[j]]; } } return cost; } int main() { while(scanf("%d%d",&n,&m)!=EOF,n+m){ int k=0; init(k); int min_id=N; double _ratio = INF*1.0; input(); for(int i=0;i<=k;i++){ int num = state[i]; int t =0,V=0; for(int j=0;j<n;j++){ if((num>>j)&1){ ///这里代表第j+1个点要选进去 a[t++] = j+1; V += weight[j+1]; } } int cost = prim(t,a[0]); double temp1 = cost*1.0/V; if(temp1<_ratio){ _ratio = temp1; for(int i=0;i<t;i++) result[i] = a[i]; } } for(int i=0;i<m-1;i++){ printf("%d ",result[i]); } printf("%d\n",result[m-1]); } }