poj 2349 求MST中第S大的权值

题目大意:

  有一些炮台,如果这个炮台有卫星接收器,那么任意两个有卫星接收器的炮台可以通信,不受距离限制;否者,两个炮台之间只能通过对讲机通信,这是受距离限制的。要买一种对讲机,用在需要的炮台上,要求所有炮台两两之间可以直接或者间接通信,问要买通信距离D至少为多少的对讲机可以满足要求。

有S个卫星接收器,那么就可以减少S-1个距离开销。要让D尽可能小,就让这S-1个距离开销最大,所以,想法就是,求这些点的最小生成树,然后把所选的边排序,第S大的边的权值就是所求。
假如有4个点,2个卫星,那么最长的那条边可以用卫星 ,第2长的边就是最小的D,

Sample Input

1 //T
2 4 //卫星数量 结点数量
0 100
0 300
0 600
150 750
Sample Output

212.13

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 # include <algorithm>
 5 # include <cmath>
 6 # define LL long long
 7 using namespace std ;
 8
 9 const int INF=0x3f3f3f3f;
10 const int MAXN=510;
11 bool vis[MAXN];
12 double lowc[MAXN];
13 int n ;
14 int l ;
15 double cost[MAXN][MAXN] ;
16 double edge[MAXN] ;
17
18 struct poin
19 {
20     int x ;
21     int y ;
22 }p[MAXN];
23
24 bool cmp(double x , double y)
25 {
26     return x > y ;
27 }
28
29 void Prim()//点是0~n-1
30 {
31     l = 0 ;
32     memset(vis,false,sizeof(vis));
33     memset(edge,0,sizeof(edge));
34     vis[0]=true;
35     for(int i=1;i<n;i++)lowc[i]=cost[0][i];
36     for(int i=1;i<n;i++)
37     {
38         double minc=INF;
39         int p=-1;
40         for(int j=0;j<n;j++)
41             if(!vis[j]&&minc>lowc[j])
42             {
43                 minc=lowc[j];
44                 p=j;
45             }
46             if(minc==INF)return ;//原图不连通
47
48             edge[l] = minc ;
49             l++ ;
50             vis[p]=true;
51             for(int j=0;j<n;j++)
52                 if(!vis[j]&&lowc[j]>cost[p][j])
53                     lowc[j]=cost[p][j];
54     }
55     return ;
56 }
57
58 int main()
59 {
60
61   //  freopen("in.txt","r",stdin) ;
62     int T ;
63     scanf("%d" , &T) ;
64     while(T--)
65     {
66         int s ;
67         scanf("%d %d" ,&s , &n) ;
68         int i , j ;
69         for (i = 0 ; i < n ; i++)
70             for (j = 0 ; j < n ; j++)
71                cost[i][j] = INF ;
72         for (i = 0 ; i < n ; i++)
73             scanf("%d %d" , &p[i].x , &p[i].y) ;
74         for (i = 0 ; i < n ; i++)
75             for (j = i+1 ; j < n ; j++)
76             {
77                 double t = sqrt((double)(p[i].x - p[j].x) * (p[i].x - p[j].x) + (p[i].y - p[j].y) * (p[i].y - p[j].y)) ;
78                 cost[i][j] = t ;
79                 cost[j][i] = t ;
80             }
81         Prim() ;
82         sort(edge,edge+l,cmp) ;
83         printf("%.2lf\n" , edge[s-1]) ;
84
85
86     }
87     return 0 ;
88 }

时间: 2024-11-08 05:02:29

poj 2349 求MST中第S大的权值的相关文章

POJ 2104 求序列里第K大 主席树裸体题

给定一个n的序列,有m个询问 每次询问求l-r 里面第k大的数字是什么 只有询问,没有修改 可以用归并树和划分树(我都没学过..囧) 我是专门冲着弄主席树来的 对主席树的建树方式有点了解了,不过这题为什么是在主席树里面这么操作的 还是有点不懂,今天照着模板敲了一遍就打多校了 再研究吧 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using name

POJ #2485 Highways MST中的最大边权

Description 问题描述:链接 思路 题目很直接,容易看出建的图是一张完全图,需要求出图中最小生成树的最大边权.由于数据上界已经定死了,那么选择用静态邻接表存建图.由于图是稠密图,那么求MST的话就选择 prim . 做完 POJ #2253 Frogger 变种Dijkstra 后再做这个就很有感觉了.其实prim中的核心操作就是记录并更新点v到树的最短距离,然后把所有最短距离之中的最小值选出,将该点其加入树集.这个树集与dijkstra中的点集是异曲同工的. 能用 scanf 的话尽

POJ 2349 Arctic Network (最小生成树第K大(小)边)

Arctic Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13108   Accepted: 4256 Description The Department of National Defence (DND) wishes to connect several northern outposts by a wireless network. Two different communication tec

poj 1751 输出MST中新加入的边

给出结点的坐标 以及已建好的边 要输出MST中加入的边(已建好的边就不用输出了)结点的编号从1开始注意这题只有一组数据 不能用多组输入 否则就超时(在这被坑惨了Orz) Sample Input 91 50 0 3 24 55 10 45 21 25 331 39 71 2Sample Output 1 63 74 95 78 3 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 #

poj 2559求柱形图中最大矩形

两种解法.当中一种是用单调栈. 我想到的是第二种:最大的矩形,中间一定有个最矮的某个单位矩形.所以求出每一个包括矩形histogram[i]的最大矩形的面积.输出这些面积中最大那个就可以. key:用两个数组记录histogram[i]左右两边第一个比它小的单位矩形的序号leftLowerId[i]和rightLowerId[i].那么对于histogram[i],它自己的最大矩形面积就是(rightLowerId[i] - leftLowerId[i] - 1) *  histogram[i]

求数组中第k大的数(分治法)

思想:快排 因为单趟排序是使选定的king值到其应该到的位置,所以每次判断这个king的正确位置是否是第K大数的位置即可 #include <iostream> using namespace std; //快排中的单趟排序 int PartSort(int* arr,int start,int end) { int first = start; int last = end; int tmp = arr[first]; int key = first; while (first < l

poj 2485 求最小生成树中 最大的一个权值

Sample Input 1 //T 3 //n0 990 692 //邻接矩阵990 0 179692 179 0Sample Output 692 prim 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6 # define LL long long 7 using na

poj 1961 (求字符串中的重复子串)

Sample Input 3aaa12aabaabaabaab0Sample Output Test case #12 23 3 Test case #22 2 //aa有2个a6 2 //aabaab有2个aab9 312 4 0  1  2 3 4 5 6 7 8 9 10 11 a  a b a a b  a a b a a b     的next数组为-1 0 1 0 1 2 3 4 5 6 7 8 9 1 #include<stdio.h> 2 #include<iostrea

用C随机产生的正整数存到数组中,并求数组中的所有元素最大值、最小值、平均值以及各元素之和,及第二大值。

用 C 求一组随机数的第二大值,不能通过对整体排序求得 1 随机产生20个[10 , 50]的正整数存到数组中,并求数组中的所有元素最大值.最小值.平均值以及各元素之和,及第二大值.        int a[20];    int sum = 0; //存储数组元素的和    //为数组赋值    printf("数组中的元素为:\n ");    for (int i = 0; i < 20; i ++) {        a[i] = arc4random() % 41 +