ACM第四站————最小生成树(克鲁斯卡尔算法)

都是生成最小生成树,库鲁斯卡尔算法与普里姆算法的不同之处在于——库鲁斯卡尔算法的思想是以边为主,找权值最小的边生成最小生成树。

主要在于构建边集数组,然后不断寻找最小的边。

同样的题目:最小生成树

题目描述
求一个连通无向图的最小生成树的代价(图边权值为正整数)。
输入
第 一行是一个整数N(1<=N<=20),表示有多少个图需要计算。以下有N个图,第i图的第一行是一个整数M(1<=M& lt;=50),表示图的顶点数,第i图的第2行至1+M行为一个M*M的二维矩阵,其元素ai,j表示图的i顶点和j顶点的连接情况,如果 ai,j=0,表示i顶点和j顶点不相连;如果ai,j>0,表示i顶点和j顶点的连接权值。
输出
每个用例,用一行输出对应图的最小生成树的代价。
样例输入
1
6
0 6 1 5 0 0
6 0 5 0 3 0
1 5 0 5 6 4
5 0 5 0 0 2
0 3 6 0 0 6
0 0 4 2 6 0
样例输出
15
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>

using namespace std;
#define INF 0xffffff
const int maxn = 25 ;
int n, num;
int G[maxn][maxn];
int a[maxn];
struct Edges//边集数组
{
    int Start ;
    int End;
    int weight;
    bool operator < (const Edges& a) const
    {
        return weight < a.weight ;
    }
}edges[maxn];

int get_Edges()//构建边集数组
{
    int len = 0 ;
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            if( G[i][j] )
            {
                edges[len].Start = i ;
                edges[len].End = j ;
                edges[len].weight = G[i][j] ;
                ++ len ;
            }
        }
    }
    sort(edges,edges+len);
    return len ;
}

int Find(int *p, int num)
{
    while( p[num] > 0 )
        num = p[num] ;
    return num ;
}

void kruskal()
{
    int cnt = get_Edges();
    memset(a,0,sizeof(a));
    int sum = 0 ;
    for(int i=0; i<cnt; i++)
    {
        int x = Find(a, edges[i].Start);
        int y = Find(a,edges[i].End);
        if( x != y )
        {
            a[x] = y ;
            sum += edges[i].weight;
            //打印顶点以及对应权值
            //printf("%d %d == %d", edges[i].Start, edges[i].End, edges[i].weight);
        }
    }
    cout << sum << endl ;
}

int main()
{
    int T ;
    cin >> T ;
    while( T -- )
    {
        cin >> n ;
        for(int i=0; i<n; i++)
            for(int j=0; j<n; j++)
                cin >> G[i][j] ;
        kruskal();
    }

    return 0;
}
低调做人,高调做事。
原文地址:https://www.cnblogs.com/Asimple/p/5551307.html