写了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好啊~~