Chinaunix首页 | 论坛 | 博客
  • 博客访问: 469274
  • 博文数量: 117
  • 博客积分: 3195
  • 博客等级: 中校
  • 技术积分: 1156
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-04 01:44
文章分类

全部博文(117)

文章存档

2012年(5)

2011年(5)

2010年(46)

2009年(61)

我的朋友

分类:

2009-08-30 16:25:38

Memory: 256K Time: 47MS

解题思路

题意:

    John要用最少的光纤去连接所有的农场。最小生成树问题。

思路:

    Prim算法和kruskal算法都可以用,prim更简单也更合适,但是为了复习,就用了后者。把各条边放在一个数组里,非递减排序,从小到大一次看他们的顶点是不是在同一个集合中,不是的话把权加起来,并合并。寻找祖先节点的时候要用到并查集里面的压缩路径,合并的时候把高度小的树的祖先指向高度大的祖先也可以优化。由于没搞清楚无向图的边的个数和顶点的个数的关系,RE了好几次。

源程序

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#define N 110
#define M N*(N-1)/2

typedef struct
{
    int from;
    int to;
    int weight;
}edge;

edge e[M];
int parent[M];
int rank[M];

int find(int x)
{
    int y, z;

    y = x;
    while(parent[y] != y)
        y = parent[y];
    while(x != y)
    {
        z = parent[x];
        parent[x] = y;
        x = z;
    }
    return y;
}

void _union(int x, int y)
{
    if(rank[x] > rank [y])
    {
        parent[y] = x;
    }
    else
    {
        if(rank[x] == rank[y])
            rank[y]++;
        parent[x] = y;
    }
}

int cmp(const void *p, const void *q)
{
    return ((edge *)p)->weight > ((edge *)q)->weight ? 1 : -1;
}

int main()
{
    int i, j, x, a, k, y;
    int n, sum;
    freopen("in.txt", "r", stdin);
    while(scanf("%d", &n) != EOF)
    {
        k = 0;
        memset(e, 0, sizeof(e));
        memset(rank, 0, sizeof(rank));
        memset(parent, 0, sizeof(parent));
        for(i=0; i<n; i++)
            for(j=0; j<n; j++)
            {
                if(j <= i)
                    scanf("%d", &a);
                else
                {
                    scanf("%d", &e[k].weight);
                    e[k].from = i+1;
                    e[k].to = j+1;
                    parent[k] = k;
                    k++;
                }
            }
        qsort(e, k, sizeof(e[0]), cmp);
        sum = 0;
        for(i=0; i<k; i++)
        {
            x = find(e[i].from);
            y = find(e[i].to);
            if(x != y)
            {
                printf("%d %d\n", e[i].from, e[i].to);
                sum += e[i].weight;
                _union(x, y);
            }
        }
        printf("%d\n", sum);
    }
    getch();
    return 0;
}

阅读(1043) | 评论(0) | 转发(0) |
0

上一篇:kruskal算法2

下一篇:poj 1308 Is It A Tree?

给主人留下些什么吧!~~