POJ 2728 二分+最小生成树

题意:给n个点,可以将每个点的x,y的欧几里得距离(就是坐标系里两点距离公式)看作距离,z的差值即为费用差,求的是所有最小生成树中的min(边费用和/边距离和)。

思路:其实挑战P143有类似的列题,用的是二分枚举答案的方法,只不过不是树。这一题仅仅需要将题给图找出最小生成树,然后同样枚举即可。

虽然网上有许多高级的名词什么最优比率xxx之类的。。以及迭代的方法,不过我认为用二分也很好,易于想到也可以加深理解。

  1 #include <iostream>
  2
  3 #include <string>
  4
  5 #include <cstdio>
  6
  7 #include <cstring>
  8
  9 #include <cstdlib>
 10
 11 #include <algorithm>
 12
 13 #include <cmath>
 14
 15 #define MAXN 1005
 16
 17 #define INF 1000000000
 18
 19 #define eps 1e-7
 20
 21 using namespace std;
 22
 23 int n;
 24
 25 double Edge[MAXN][MAXN], lowcost[MAXN];
 26
 27 int nearvex[MAXN];
 28
 29 struct Point
 30
 31 {
 32
 33     int x, y, z;
 34
 35 }p[MAXN];
 36
 37 double cal(int a, int b)
 38
 39 {
 40
 41     return sqrt(1.0 * (p[a].x - p[b].x) * (p[a].x - p[b].x) + 1.0 * (p[a].y - p[b].y) * (p[a].y - p[b].y));
 42
 43 }
 44
 45 double prim(int src, double l)
 46
 47 {
 48
 49     double cost = 0, len = 0;
 50
 51     double sum = 0;
 52
 53     for(int i = 1; i <= n; i++)
 54
 55     {
 56
 57         nearvex[i] = src;
 58
 59         lowcost[i] = abs(p[src].z - p[i].z) - Edge[src][i] * l;
 60
 61     }
 62
 63     nearvex[src] = -1;
 64
 65     for(int i = 1; i < n; i++)
 66
 67     {
 68
 69         double mi = INF;
 70
 71         int v = -1;
 72
 73         for(int j = 1; j <= n; j++)
 74
 75             if(nearvex[j] != -1 && lowcost[j] < mi)
 76
 77             {
 78
 79                 v = j;
 80
 81                 mi = lowcost[j];
 82
 83             }
 84
 85         if(v != -1)
 86
 87         {
 88
 89             cost += abs(p[nearvex[v]].z - p[v].z);
 90
 91             len += Edge[nearvex[v]][v];
 92
 93             nearvex[v] = -1;
 94
 95             sum += lowcost[v];
 96
 97             for(int j = 1; j <= n; j++)
 98
 99             {
100
101                 double tmp = abs(p[v].z - p[j].z) - Edge[v][j] * l;
102
103                 if(nearvex[j] != -1 && tmp < lowcost[j])
104
105                 {
106
107                     lowcost[j] = tmp;
108
109                     nearvex[j] = v;
110
111                 }
112
113             }
114
115         }
116
117     }
118
119     return sum;
120
121 }
122
123 int main()
124
125 {
126
127     while(scanf("%d", &n) != EOF && n)
128
129     {
130
131         for(int i = 1; i <= n; i++)
132
133             scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].z);
134
135         for(int i = 1; i <= n; i++)
136
137             for(int j = 1; j <= n; j++)
138
139                 Edge[i][j] = cal(i, j);
140
141         double low = 0, high = 10.0;             //其实二分20多次已经很足够了
142
143         double l = 0.0, r = 100.0, mid;
144
145         while(r - l > eps)
146
147         {
148
149             mid = (l + r) / 2;
150
151             if(prim(1, mid) >= 0) l = mid;
152
153             else r = mid;
154
155         }
156
157         printf("%.3f\n", r);
158
159     }
160
161     return 0;
162
163 }

原文地址:https://www.cnblogs.com/llllrj/p/9402294.html

时间: 2024-08-05 09:40:57

POJ 2728 二分+最小生成树的相关文章

poj 2728 Desert King(最小比率生成树,迭代法)

引用别人的解释: 题意:有n个村庄,村庄在不同坐标和海拔,现在要对所有村庄供水,只要两个村庄之间有一条路即可, 建造水管距离为坐标之间的欧几里德距离(好象是叫欧几里德距离吧),费用为海拔之差 现在要求方案使得费用与距离的比值最小 很显然,这个题目是要求一棵最优比率生成树, 概念 有带权图G, 对于图中每条边e[i], 都有benifit[i](收入)和cost[i](花费), 我们要求的是一棵生成树T, 它使得 ∑(benifit[i]) / ∑(cost[i]), i∈T 最大(或最小). 这

poj 2728 Desert King(最优比率生成树,01分数规划)

http://poj.org/problem?id=2728 大致题意:有n个村庄,输入每个村庄的位置和高度,这n个村庄要连在一起,村与村之间的长度为他们之间的欧几里得距离,花费是两村之间的高度差,要求连在一起的花费和与距离和之比的最小值. 思路:明显的最优比率生成树.二分答案λ,每条边重新赋权c[i] - λd[i] ,因为要求比值最小,那么对于所有的生成树,它们的f[λ]必须>=0,所以只需求得基于最小生成树的f'[λ],当f'[λ] = 0时即找到了正解λ*. 二分: #include <

POJ 2728 Desert King (最优比率生成树---01分数规划)

题目地址:POJ 2728 01分数规划的应用之一-最优比率生成树. 跟普通的01分数规划类似,只是这题的验证函数改成了最小生成树来验证.弱用的迭代法. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map>

poj 1679 判断最小生成树是否唯一

/* 只需判断等效边和必选边的个数和n-1的关系即可 */ #include<stdio.h> #include<stdlib.h> #define N 110 struct node { int u,v,w; }f[N*N*2]; int cmp(const void *a,const void*b) { return (*(struct node *)a).w-(*(struct node *)b).w; } int pre[N]; int find(int x) { if(x

poj 3723 Conscription(最小生成树拓展)

Conscription Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7702   Accepted: 2667 Description Windy has a country, and he wants to build an army to protect his country. He has picked up N girls and M boys and wants to collect them to be

POJ 2485-Highways(最小生成树prim)

Highways Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22433   Accepted: 10341 Description The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has no public highways. So the traffic is difficult in Flatopia. The Fl

poj 1861(最小生成树)

Description Andrew is working as system administrator and is planning to establish a new network in his company. There will be N hubs in the company, they can be connected to each other using cables. Since each worker of the company must have access

poj 2485(prim最小生成树)

Highways Description The island nation of Flatopia is perfectly flat. Unfortunately, Flatopia has no public highways. So the traffic is difficult in Flatopia. The Flatopian government is aware of this problem. They're planning to build some highways

POJ 1258 Agri-Net (最小生成树+Prim)

Agri-Net Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 39820   Accepted: 16192 Description Farmer John has been elected mayor of his town! One of his campaign promises was to bring internet connectivity to all farms in the area. He nee