POJ 2728 Desert King(最优比率生成树 01分数规划)
http://poj.org/problem?id=2728
题意:
在这么一个图中求一棵生成树,这棵树的单位长度的花费最小是多少?
思路:
最优比率生成树,也就是01分数规划,二分答案即可,题目很简单,因为这题是稠密图,所以用prim算法会好点。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 const int INF = 0x3f3f3f3f; 14 const int maxn=1000+5; 15 const double eps=1e-6; 16 17 int n; 18 int x[maxn],y[maxn],z[maxn]; 19 bool vis[maxn]; 20 double cost[maxn][maxn],dis[maxn][maxn],d[maxn]; 21 22 23 double prim(double x) 24 { 25 double sum=0; 26 memset(vis,0,sizeof(vis)); 27 vis[1]=1; d[1]=0; 28 for(int i=2;i<=n;i++) d[i]=cost[1][i]-x*dis[1][i]; 29 for(int i=2;i<=n;i++) 30 { 31 double MIN=INF; 32 int pos; 33 for(int j=1;j<=n;j++) 34 { 35 if(!vis[j] && d[j]<MIN) 36 { 37 pos=j; 38 MIN=d[j]; 39 } 40 } 41 vis[pos]=1; 42 sum+=MIN; 43 for(int j=1;j<=n;j++) 44 { 45 if(!vis[j] && d[j]>cost[pos][j]-x*dis[pos][j]) 46 d[j]=cost[pos][j]-x*dis[pos][j]; 47 } 48 } 49 return sum; 50 } 51 52 int main() 53 { 54 //freopen("in.txt","r",stdin); 55 while(~scanf("%d",&n) && n) 56 { 57 for(int i=1;i<=n;i++) 58 { 59 scanf("%d%d%d",&x[i],&y[i],&z[i]); 60 for(int j=1;j<i;j++) 61 { 62 cost[i][j]=cost[j][i]=abs(z[j]-z[i]); 63 dis[i][j]=dis[j][i]=sqrt((double)(y[i]-y[j])*(y[i]-y[j])+(double)(x[i]-x[j])*(x[i]-x[j])); 64 } 65 } 66 double l=0,r=100000; 67 double ans=0; 68 while(r-l>=eps) 69 { 70 double mid=(l+r)/2.0; 71 if(prim(mid)>=0) 72 { 73 ans=mid; 74 l=mid; 75 } 76 else r=mid; 77 } 78 printf("%.3f\n",ans); 79 } 80 return 0; 81 }