浏览器标题切换
浏览器标题切换end

POJ2349 - Arctic Network - 最小生成树变形

题意

给出\(T\)组数据,每组数据第一行给出\(s\)\(p\),分别代表卫星数和哨所数,接下来给出\(p\)行代表\(p\)个哨所的坐标。

带有卫星的两个哨所,相互之间可以进行通信;否则 需要俩哨所之间距离小于等于\(d\)才可以通过无线电通信。

我们需要满足每个哨所之间都有路径,确定最小的\(d\)

输出连接网络所需的最小\(d\),答案保留2个小数点。

PS:我感觉这个英文还是右点难理解,毕竟中文我都看了半天……

思路

这题不难,最小生成树改一下就可以过,但是我写了2h+……

首先我们需要知道一个定理

如果去掉所有权值大于\(d\)的边后最小生成树被分割成k个连通分支,图也会被分割成k个连通分支。

所以,由此可得,我们只需要给每个连通支分一个卫星即可,最短距离\(D\)就变成了去掉 大于\(D\) 后的 最大的边 ,

\(X\)长的边

AC代码

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<list>
#include<stdlib.h>
#include<map>
#include<stack>
#include<stdio.h>
#include<queue>
using namespace std;
typedef long long ll;
#define sc(T) scanf("%d",&T)
#define scc(x,y) scanf("%d %d",&x,&y)
#define pr(T) printf("%d\n",T)
#define f(a,b,c) for (int a=b;a<c;a++)
#define ff(a,b,c) for (int a=b;a>c;a--)
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
#define eps 1e-9
#define PI acos(-1)

const int N=520;
int s,p,f[N];
double book[N*N];
struct node
{
    int x,y; //记住!!!改为double结果不对?为啥!?
    double w;
} e[N*N],dis[N*N];

int getf(int x)
{
    if(x==f[x])
        return x;
    return f[x]=getf(f[x]);
}

int merge(int x,int y)
{
    int t1=getf(x);
    int t2=getf(y);
    if(t1!=t2)
    {
        f[t2]=t1;
        return 1;
    }
    return 0;
}

bool cmp1(node x,node y)
{
    return x.w<y.w;
}

double d(node a,node b)
{
    return sqrt(1.0*(a.x-b.x)*(a.x-b.x)+1.0*(a.y-b.y)*(a.y-b.y));
}

int main()
{
    int T;
    sc(T);
    while(T--)
    {
        mem(book,0);
        scc(s,p);//卫星数、哨所数
        for(int i=1; i<=p; i++)
        {
            f[i]=i;
            scc(e[i].x,e[i].y);
        }
        int k=0;
        for(int i=1; i<p; i++)
        {
            for(int j=i+1; j<=p; j++)
                // f(j,0,p)
                dis[k].x=i,dis[k].y=j,dis[k++].w=d(e[i],e[j]);
        }
        sort(dis,dis+k,cmp1);
//        for(int i=0;i<k;i++)
//        {
//            cout<<dis[i].x<<"**"<<dis[i].y<<"***"<<dis[i].w<<endl;
//        }
        int w=0,cnt=0;
        for(int i=0; i<k; i++)
        {
            if(merge(dis[i].x,dis[i].y))
                book[w++]=dis[i].w,cnt++;
            if(cnt==p-1)
            {
                //book[w++]=dis[i].w;
                break;
            }
        }
        sort(book,book+w);
//        for(int i=0;i<w;i++)
//            cout<<book[i]<<"***"<<endl;
        printf("%.2f\n",book[p-1-s]);//w-p+1//p-1-s
    }
    return 0;
}
posted @ 2020-09-22 16:12  抓水母的派大星  阅读(141)  评论(0编辑  收藏  举报