hdu 2489 MST+dfs

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 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值