http://acm.hdu.edu.cn/showproblem.php?pid=2489
题目大意是有n个顶点的无向完全图,要你选m个点,使得m个点构成的图的m-1条边的权重之和比上m个点的值的和最小,即Sum(edge weight)/Sum(point weight)最小;
由于题目的数据很小,因此我就直接暴力了。。。
就是从n个点中先选m个点,对应一个最小值,然后对这m个点进行搜索就可以了。。。
如果一开始就从第一个点就开始dfs,那么就可以保证最后的结果就是题目要求的。。。
View Code
1 #include<iostream> 2 const int N=20; 3 const int inf=10000000; 4 using namespace std; 5 6 int node[N];//点的权值 7 int recode[N];//保存点 8 int edge[N][N]; 9 int lowcost[N]; 10 int map[N][N];//用来保存边 11 int path[N]; //保存路径 12 int n,m; 13 double MIN; 14 15 double prim(int v0){ 16 double sum=0; 17 for(int i=1;i<=m;i++){ 18 lowcost[i]=map[v0][i]; 19 } 20 lowcost[v0]=-1; 21 for(int i=1;i<m;i++){ 22 int min=inf,v=-1; 23 for(int j=1;j<=m;j++){ 24 if(lowcost[j]!=-1&&lowcost[j]<min){ 25 v=j,min=lowcost[j]; 26 } 27 } 28 if(v!=-1){ 29 sum+=lowcost[v]; 30 lowcost[v]=-1; 31 for(int k=1;k<=m;k++){ 32 if(lowcost[k]!=-1&&map[v][k]<lowcost[k]){ 33 lowcost[k]=map[v][k]; 34 } 35 } 36 } 37 } 38 return sum; 39 } 40 void dfs(int v0,int count){ 41 recode[count]=v0; 42 if(count==m){ 43 for(int i=1;i<=m;i++){ 44 map[i][i]=0; 45 for(int j=i+1;j<=m;j++){ 46 map[i][j]=map[j][i]=inf; 47 } 48 } 49 for(int i=1;i<=m;i++){ 50 for(int j=1;j<=m;j++){ 51 map[i][j]=edge[recode[i]][recode[j]]; 52 } 53 } 54 double s1=prim(1),s2=0; 55 for(int i=1;i<=m;i++){ 56 s2+=node[recode[i]]; 57 } 58 double s=s1/s2; 59 if(s<MIN){ 60 MIN=s; 61 //保存路径 62 for(int i=1;i<=m;i++) 63 path[i]=recode[i]; 64 } 65 } 66 for(int i=v0+1;i<=n;i++) 67 dfs(i,count+1); 68 } 69 70 int main(){ 71 while(scanf("%d%d",&n,&m)!=EOF){ 72 if(n==0&&m==0)break; 73 for(int i=1;i<=n;i++){ 74 scanf("%d",&node[i]); 75 } 76 for(int i=1;i<=n;i++){ 77 for(int j=1;j<=n;j++){ 78 scanf("%d",&edge[i][j]); 79 } 80 } 81 MIN=1e18; 82 for(int i=1;i<=n;i++) 83 dfs(i,1); 84 printf("%d",path[1]); 85 for(int i=2;i<=m;i++){ 86 printf(" %d",path[i]); 87 } 88 printf("\n"); 89 } 90 return 0; 91 }