您的位置:首页 > 其它

Kruskal 最小生成树的总结

2008-12-21 10:59 471 查看
写了3,4天的最小生成树,里边写了报告和没写的加起来也有十题左右了。发现这些简单的算法里头有不少的pin。特别是2421让人抓狂,bug一个接一个,wa了不下十数次后,在波波的指导下成功的ac了,后来自己又找到了原来程序的几个bug。
原先写这篇报告的时候以为Kruskal比Prim优秀许多。后来波波跟我说Prim也是很强的,于是我分别用Kruskal和Prim写了Poj1789,发现原来Prim也是很strong的,用的时间几乎只有Kruskal的20%,囧。于是现在把这篇报告改为Kruskal最小生成树总结,顺便把标程贴出来以后好找~~

下面的是Kruskal:

//这段代码用Kruskal来解决

#include <stdio.h>

#include <stdlib.h>

#include <memory.h>

#include <algorithm>

using namespace std;

// 边类型

typedef struct Edge{

int x;

int y;

int weigh;

bool operator() ( Edge a,Edge b) {

return (a.weigh < b.weigh);

}

}Edge;

//最多可能的边

Edge edge[251001];

int parent[501];

//用于qsort()的比较函数

int compare(const void*a,const void *b)

{

return ((Edge*)a)->weigh - ((Edge*)b)->weigh;

}

// 找父节点并压缩路径

int Find(int x)

{

if( parent[x] >= 0)

parent[x] = Find(parent[x]);

else

return x;

return parent[x];

}

// 合并集合

void Union(int x,int y)

{

x = Find(x);

y = Find(y);

// 注意:这里的重边判断很重要

if( x == y)

return ;

if(parent[x] < parent[y])

parent[y] = x;

else

if(parent[x] > parent[y])

parent[x] = y;

else {

parent[x]--;

parent[y] = x;

}

}

int main()

{

int m,n;

int count = 0;

scanf("%d",&n);

for( int i = 0; i < n; i++) {

scanf("%d",&m);

memset(parent,-1,m * sizeof(int));

for( int j = 0; j < m; j++)

for( int k = 0; k < m; k++) {

scanf("%d",&edge[count].weigh);

edge[count].x = j;

edge[count++].y = k;

}

sort(edge,edge + m * m,Edge());

count = 1;

int max;

// 忽略那些为0的节点,有m个,然后从小到大去边

for( int j = m; j < (m * m) && count < m; j++)

if(Find(edge[j].x) != Find(edge[j].y)) {

count ++;

Union(edge[j].x,edge[j].y);

max = edge[j].weigh;

}

printf("%d/n",max);

}

}

唉,还是有parent好啊~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: