【最小比例树】Minimal Ratio Tree

Minimal Ratio Tree

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3391    Accepted Submission(s): 1027


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
 
题目大意:
  让你在N个点的联通图中,找出M个点联通子图的最小比例生成树、
解法:(DFS+最小生成树):
  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <algorithm>
  4 #include <math.h>
  5 #include <queue>
  6 #define INF 1e9
  7 #define EXP (1e-9)
  8 #define MAX 200
  9 using namespace std;
 10 int Sign;
 11 int First[MAX];
 12 int P_V[MAX];/*点权*/
 13 int P[MAX]; /*点记录*/
 14 int IDD[MAX];/*点标记*/
 15 int Map[MAX][MAX];
 16 int Min_P[MAX];/*记录答案坐标*/
 17 double Min_V,Vlue;/*记录最小比例*/
 18 int N,M;
 19 struct Poin
 20 {
 21     int to,v,next;
 22     friend bool operator<(Poin a,Poin b)
 23     {
 24         return a.v>b.v;
 25     }
 26 }ID[MAX*5];
 27 
 28 void Cread(int n){for(int i=0;i<=n;i++)First[i]=0;Sign=1;}/*初始化*/
 29 
 30 void Add_E(int x,int y,int z)
 31 {
 32     ID[Sign].to=y;
 33     ID[Sign].v=z;
 34     ID[Sign].next=First[x];
 35     First[x]=Sign++;
 36 }
 37 
 38 int Prim()/*Prim+堆维护*/
 39 {
 40     priority_queue <Poin>Q;
 41     Poin NUM;
 42     int PP=P[1],i,NN=M,Sum=0,Vis[MAX]={0};
 43     for(i=1;i<=M;i++)Vis[P[i]]=1;
 44     Vis[PP]=0;NN--;
 45     for(i=First[PP];i;i=ID[i].next){Q.push(ID[i]);}
 46     while(!Q.empty()&&NN)
 47     {
 48         NUM=Q.top();Q.pop();
 49         if(Vis[NUM.to])
 50         {
 51             PP=NUM.to;Vis[PP]=0;
 52             Sum+=NUM.v;NN--;
 53             for(i=First[PP];i;i=ID[i].next)
 54                 Q.push(ID[i]);
 55         }
 56     }
 57     if(!NN)return Sum;
 58     else return -1;
 59 }
 60 
 61 
 62 void DFS(int d,int ii)
 63 {
 64     P[d]=ii;
 65     if(d==M)
 66     {
 67         double E_Sum,P_Sum=0;
 68         for(int i=1;i<=M;i++)P_Sum+=P_V[P[i]];
 69         E_Sum=Prim();
 70         Vlue=(double)E_Sum/((double)P_Sum);
 71         if(Vlue-Min_V<-EXP)
 72         {
 73             for(int i=1;i<=M;i++)Min_P[i]=P[i];
 74             Min_V=Vlue;
 75         }
 76       //  printf("\t%.5lf %.5lf %.5lf\n",E_Sum,P_Sum,Vlue);
 77         return ;
 78     }
 79     for(int i=ii+1;i<=N;i++)
 80     {
 81         if(IDD[i])
 82         {
 83             IDD[i]=0;
 84             DFS(d+1,i);
 85             IDD[i]=1;
 86         }
 87     }
 88     return ;
 89 }
 90 
 91 int main()
 92 {
 93     int i,j,k,A,B,C;
 94     while(scanf("%d%d",&N,&M)!=EOF)
 95     {
 96         if(N==0&&M==0)break;
 97         Min_V=(double)INF;Sign=1;
 98         for(i=1;i<=N;i++)scanf("%d",&P_V[i]);
 99         for(i=1;i<=N;i++)
100             for(j=1;j<=N;j++)
101                 scanf("%d",&Map[i][j]);
102         Cread(N);
103         for(i=1;i<=N;i++)
104             for(j=i+1;j<=N;j++)
105             {Add_E(i,j,Map[i][j]);Add_E(j,i,Map[i][j]);}
106         for(i=1;i<=N;i++)IDD[i]=1;
107         for(i=1;i<=N-M+1;i++)
108         {
109             IDD[i]=0;
110             DFS(1,i);
111             IDD[i]=1;
112         }
113         sort(Min_P+1,Min_P+M+1);
114         for(i=1;i<=M;i++)
115         {
116             if(i!=1)putchar(32);
117             printf("%d",Min_P[i]);
118 
119         }putchar(10);
120     }
121     return 0;
122 }
View Code

 

 
posted @ 2015-08-17 15:27  Wurq  阅读(281)  评论(0编辑  收藏  举报