Sicily Single-link Clustering| Prim算法

本文介绍了如何使用Prim算法解决Sicily单链聚类问题,即找到二维空间中n个节点的最小生成树并删除第k-1条最长边。给出的解法包括算法原理、输入输出格式以及代码实现。
摘要由CSDN通过智能技术生成

Single-link Clustering
Total: 229 Accepted: 90

Time Limit: 1sec Memory Limit:256MB
Description
Given n nodes in a two-dimensional space, we want to use single-link custering method to find k clusters. This is equivalent to finding an MST (Minimum spanning tree) of these nodes and deleting k-1 longest edges.

Your job is to output the length of the (k-1)-th longest edges of the MST.

Input
There are multiple cases. For each case, the first line includes n and k (2<=k<=n<=100). The following n lines give the coordinates of n nodes. You may use Euclidean distance to measure the distance between two nodes.

Output
For each case, output the length of the (k-1)-th longest edges. The precision is set to 2 digits after the decimal point.

Sample Input
Copy sample input to clipboard
6 2
1 1
2 1
1 2
3 3
4 2
4 3
Sample Output
2.24

题意:将二维空间的n个点分成k类。方法为:根据这n个点得到最小生成树,然后删除第k-1条最长的边。
输入:先输入n和k,随后输入n个点的x、y轴左标。
输出:第k-1条最长的边的值
解法:使用prim算法得到最小生成树,用一个数组记录树的边,最后对该数组进行排序,输出第k-1个最大的值

Prim算法参考:这里

代码:

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;

const double inf=1000000007;//随便设的大数 
struct point
{
    double x,y;
};

int main()
{
    int n,k;
    while(cin>>n>>k)
    {
        point P[n];
        double G[n][n];//储存点之间的距离
        bool vis[n];//判断点是否已经访问
        double lowcost[n];//起点到其他点的最小距离
        int adjvex[n];//到顶点的最近的点

        for(int i=0;i<n;i++)
        {
            cin>>P[i].x>>P[i].y;
        }

        //得到图
        for(int i=0;i<n;i++)
        {
            G[i][i]=0;
            for(int j=i+1;j<n;j++)
            {
                G[i][j]=G[j][i]=sqrt((P[i].x-P[j].x)*(P[i].x-P[j].x)
                                    +(P[i].y-P[j].y)*(P[i].y-P[j].y));
            }
        }
        //使用prim算法 
        for(int i=0;i<n;i++)
        {
            vis[i]=false;
            adjvex[i]=0;
            lowcost[i]=G[0][i];
        }

        vis[0]=true;//设0为起点

        std::vector<double> vet;
        for(int i=1;i<n;i++)//对于剩下的n-1个点
        {
            double min=inf;
            int v=-1;
            for(int j=1;j<n;j++)//找到未访问的且距离已访问点集合最小的点
            {
                if(!vis[j]&&lowcost[j]<min)
                {
                    min=lowcost[j];
                    v=j;
                }
            }
            if(v!=-1)
            {
                vis[v]=true;
                vet.push_back(lowcost[v]);

                for(int j=1;j<n;j++)//更新离顶点最近的点和最小距离
                {
                    if(!vis[j]&&G[v][j]<lowcost[j])
                    {
                        lowcost[j]=G[v][j];
                        adjvex[j]=v;
                    }
                }
            }
        }
        //对树中的所有边从大到小排序,找到第k-1条最长的边 
        sort(vet.begin(),vet.end(),greater<double>() );
        printf("%.2lf\n",vet[k-2]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值