Single-link Clustering

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.

题目解释:对于n个二维空间点进行聚类,将n个二维空间点分成k类。这道题转化的思想就是,先生成最小生成树,然后删除k-1个最长边

输入:第一行为节点数n以及最终分类的类别数k(2<= k <= 100),后面n行,每一行包括两个数表示二维空间的点

输出:第k-1长的边的长度


#include <iostream>
#include <math.h>
#include <vector>
#include <iomanip>
using namespace std;

struct minNode
{
    int index;
    float value;
};

struct Point
{
    int x,y;
};

//Calculate the Euclidiean distance between two nodes
float CalDistance(Point a, Point b)
{
    return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}

float maxEdge(float *graph, int n)
{
    float maxLen = graph[0];
    for(int i=1;i<n;i++)
    {
        if(graph[i]>=maxLen)
            maxLen = graph[i];
    }
    return maxLen;
}

// 距i点最小距离的点
int minIndex(int i, float* graph, int n, bool *flag)
{
    float maxLen = maxEdge(graph, n);
    int j=0;
    for(int k=0;k<n;k++)
    {
        if(k==i || flag[k]==true)
            continue;
        if(graph[k] <= maxLen)
        {
            maxLen = graph[k];
            j=k;
        }
    }
    return j;
}

int main(int argc, const char * argv[]) {
    int n,k,i,j;
    while(cin >> n >> k)
    {
        vector<Point> Coordinate;
        for( i = 0; i < n; i++)
        {
            Point tmp;
            cin >> tmp.x >> tmp.y;
            Coordinate.push_back(tmp);
        }
        //开始求出图
        float graph[n][n];
        for(i = 0; i < n; i++)
        {
            for(j = 0; j <= i; j++)
            {
                graph[i][j] = graph[j][i] = CalDistance(Coordinate[i], Coordinate[j]);
            }
        }
        
        bool flag[n];
        for(i=0;i<n;i++)
        {
            flag[i] = false;
        }
        vector<float> edges;
        flag[0] = true;
        
        for(i=0;i<n-1;i++)
        {
            vector<minNode> minedges;
            for(int j=0;j<n;j++)
            {
                if(flag[j])
                {
                    int a = minIndex(j, graph[j], n, flag);
                    minNode node;
                    node.value = graph[j][a];
                    node.index = a;
                    minedges.push_back(node);
                }
            }
            
            //找出最小边
            minNode minnode = minedges[0];
            for(int j=1;j<minedges.size();j++)
            {
                if(minedges[j].value < minnode.value)
                    minnode = minedges[j];
            }
            edges.push_back(minnode.value);
            flag[minnode.index] = true;
        }
        
        //排序
        for(i =0; i< n-1; i++)
        {
            for(j =i+1; j< n-1; j++)
            {
                if(edges[j] > edges[i])
                {
                    float tmpV = edges[j];
                    edges[j] = edges[i];
                    edges[i] = tmpV;
                }
            }
        }
        
        cout << setiosflags(ios::fixed) << setprecision(2) << edges[k-2] << endl;
        
    }
    
    return 0;
}                                 

后记:

实现最小生成树的方法一般包括prim算法和Kruskal算法,这里使用的是prim算法来实现的。


代码新手,欢迎各位大神提出宝贵的意见和建议


你可能感兴趣的:(算法,sicily)