最小生成树专题

POJ1258

     Prim算法。

View Code
#include <cstdio>
#include <cstring>
#define MAXN 110

int d[MAXN][MAXN];
int edge[MAXN]; 
bool visit[MAXN];
int n;

int Prim()
{
    int i, j, k, mst = 0;
    memset(visit, false, sizeof(visit));
    memset(edge, 0x3f, sizeof(edge));
    edge[0] = 0;
    for(i = 0; i < n; i ++)
    {
        k = -1;
        for(j = 0; j < n; j ++)
            if(!visit[j] && (k == -1 || edge[j] < edge[k]))
                k = j;
        visit[k] = true;
        mst += edge[k];
        for(j = 0; j < n; j ++)
        {
            if(!visit[j] && d[k][j] && d[k][j] < edge[j]) 
                edge[j] = d[k][j];
        }
    }
    return mst;
}

int main()
{
    while(~scanf("%d", &n))
    {
        for(int i = 0; i < n; i ++)
        {
            for(int j = 0; j < n; j ++)
            {
                scanf("%d", &d[i][j]);
            }
        }
        printf("%d\n", Prim());;
    }
    return 0;
}

     Kruskal算法。

View Code
#include <cstdio>
#include <algorithm>
#define MAXN 100100
using namespace std;

int u[MAXN], v[MAXN], w[MAXN], p[MAXN], r[MAXN];
int n, m, id;

int cmp(const int i, const int j)
{
    return w[i] < w[j];
}

int find(int x)     //并查集,保证放入的边不构成环
{
    return p[x] == x ? x : p[x] = find(p[x]);
}

int Kruskal()
{
    int mst = 0;
    for(int i = 0; i < n; i ++) //初始化并查集的根节点为自己
        p[i] = i;
    for(int i = 0; i < m; i ++) // 边编号
        r[i] = i;
    sort(r, r + m, cmp);
    for(int i = 0; i < m; i ++)
    {
        int e = r[i];
        int x = find(u[e]);
        int y = find(v[e]);
        if(x != y)               // x == y表示新加入的边会构成环,所以即使当前的边是最小权值,也不能要
        {
            mst += w[e];
            p[x] = y;            // 将新加入的安全边的两个端点加入并查集,可以以任意一个点为根,所以写成p[y] = x也是可以的
        }
    }
    return mst;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    while(~scanf("%d", &n))
    {
        id = 0;
        m = n * n;
        for(int i = 0; i < n; i ++)
        {
            for(int j = 0; j < n; j ++)
            {
                u[id] = i, v[id] = j;
                scanf("%d", &w[id ++]);
            }
        }
        printf("%d\n", Kruskal());
    }
    return 0;
}

POJ2485

View Code
/*
Memory: 568K        Time: 172MS
Language: C++    Result: Accepted

*/
#include <cstdio>
#include <cstring>
#define MAXN 510
int d[MAXN][MAXN];
int min[MAXN];
bool flag[MAXN];

int n, m;

int Prim()
{
    int max = 0;
    int i, j, k;
    memset(min, 0x3f, sizeof(min));
    memset(flag, false, sizeof(flag));
    min[0] = 0;
    for(i = 0; i < n; i ++)
    {
        k = -1;
        for(j = 0; j < n; j ++)
        {
            if(!flag[j] && (k == -1 || min[j] < min[k]))
                k = j;
        }
        flag[k] = true;
        if(min[k] > max)
        {
            max = min[k];
        }
        for(j = 0; j < n; j ++)
        {
            if(!flag[j] && d[k][j] && d[k][j] < min[j])
                min[j] = d[k][j];
        }
    }
    return max;
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t --)
    {
        scanf("%d", &n);
        for(int i = 0; i < n; i ++)
        {
            for(int j = 0; j < n; j ++)
            {
                scanf("%d", &d[i][j]);
            }
        }
        printf("%d\n", Prim());
    }
    return 0;
}
View Code
/*
Memory: 820K        Time: 297MS
Language: C++    Result: Accepted
*/
#include <cstdio>
#include <algorithm>
#define MAXN 250010
using namespace std;
int w[MAXN], r[MAXN], p[MAXN], u[MAXN], v[MAXN];
int n, m;

int find(int x)
{
    return p[x] == x ? p[x] : p[x] = find(p[x]);
}

bool cmp(int i, int j)
{
    return w[i] < w[j];
}

int Kruskal()
{
    int i, max = 0;
    m = n * n;
    for(i = 0; i < n; i ++)
        p[i] = i;
    for(i = 0; i < m; i ++)
        r[i] = i;
    sort(r, r + m, cmp);
    for(i = 0; i < m; i ++)
    {
        int e = r[i];
        int x = find(u[e]);
        int y = find(v[e]);
        if(x != y)
        {
            if(w[e] > max) max = w[e];
            p[x] = y;
        }
    }
    return max;
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t --)
    {
        int id = 0;
        scanf("%d", &n);
        for(int i = 0; i < n; i ++)
        {
            for(int j = 0; j < n; j ++)
            {
                u[id] = i, v[id] = j;
                scanf("%d", &w[id ++]);
            }
        }
        printf("%d\n", Kruskal());
    }
    return 0;
}

    努力更新中……
   

原文地址:https://www.cnblogs.com/huangfeihome/p/2667474.html