POJ

来源:互联网 发布:网络之纵横天下同人 编辑:程序博客网 时间:2024/06/06 20:47

题目链接:http://poj.org/problem?id=2349

题意:s代表接收器,可以连接任何远的点,p代表有多少个点,问你除了用接收器的那几个点,其他点连接最远的最小值

思路:构造一棵最小生成树,越远的距离肯定用接收器,所以只要找到第p-s小的点就好了,直接贪心选取


代码:

#include <cstdio>#include <cmath>#include <iostream>#include <cstring>#include <algorithm>#include <queue>#include <stack>#include <vector>#include <map>#include <numeric>#include <set>#include <string>#include <cctype>#include <sstream>#define INF 0x3f3f3f3fusing namespace std;typedef long long LL;typedef pair<int, int> Q;const int maxn = 5e6 + 5;int n,p[505],cnt,S,P,num;struct point{    int x,y;}po[maxn];struct edge{    int u,v;    double cost;}e[maxn];bool cmp(edge a,edge b){    return a.cost<b.cost;}void init (int n) {for (int i=0;i<=n;i++) p[i]=i;}int Find(int x) {return p[x]==x?x: ( p[x]=Find ( p[x] ) );}bool same(int a,int b) {return Find(a)==Find(b);}void unite (int x,int y){    x=Find(x);    y=Find(y);    if (x!=y)  p[x]=y;}double dis(point a,point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}double kruskal(){    sort(e,e+cnt,cmp);    int ans=0;    for (int i=0;i<cnt;i++){        edge ee=e[i];        if (!same(ee.u,ee.v)){            unite(ee.u,ee.v);            ans++;            if (ans==num) return ee.cost;        }    }    return ans;}int main () {    //freopen ("in.txt", "r", stdin);    scanf ("%d",&n);    while (n--){        scanf ("%d%d",&S,&P);        init(P);        for (int i=0;i<P;i++){            scanf ("%d%d",&po[i].x,&po[i].y);        }        cnt=0;        for (int i=0;i<P;i++){            for (int j=i+1;j<P;j++){                e[cnt].u=i;                e[cnt].v=j;                e[cnt++].cost=dis(po[i],po[j]);            }        }        num=P-S;        printf ("%.2f\n",kruskal());    }    return 0;}