MDeath-Kid

- M I T & Y
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

ZOJ 1203 Kruskal实现

Posted on 2011-08-11 16:30  MDeath-Kid  阅读(258)  评论(0编辑  收藏  举报

找一个以前做过的MST,用堆实现一下。

Kruskal
typedef double elemt;

#define _ufind_run(x) for(;p[t=x];x=p[x],p[t]=(p[x]?p[x]:x))
#define _run_both _ufind_run(i);_ufind_run(j)

struct ufind{
int p[MAXNT],t;
void init(){memset(p,0,sizeof(p));}
void set_friend(int i,int j){_run_both;p[i]=(i==j?0:j);}
int is_friend(int i,int j){_run_both;return i==j&&i;}
}f;
struct edge {
int s,e;
elemt va;
edge(){}
edge(
int a,int b,elemt v) {
s
=a;e=b;va=v;
}
};
bool operator < (edge a,edge b) {
return a.va > b.va;
}
priority_queue
<edge> adj;


int n,m;
double x[MAXNT],y[MAXNT];

elemt kruskal(){
f.init();
int cnt = 0,a,b;
elemt sum
=0;
edge tmp;
while(cnt < n - 1 && !adj.empty()) {
tmp
= adj.top();adj.pop();
a
= tmp.s;b = tmp.e;
if(!f.is_friend(a,b))
//cnt 主要控制合并次数 最多n-1次
f.set_friend(a,b),sum+=tmp.va,cnt++;
}
return sum;
}

void init() {
SETQ(adj);
for(int i = 1;i<=n;i++) {
scanf(
"%lf %lf",&x[i],&y[i]);
}
FOR(i,
1,n) FOR(j,1,n) {
if(i == j) continue;
double tmp = sqrt((x[j]-x[i])*(x[j]-x[i])+(y[j]-y[i])*(y[j]-y[i]));
adj.push(edge(i,j,tmp));
}

}

int main() {
FOPEN
int kk = 1;
cin
>>n;
while(n) {
init();
printf(
"Case #%d:\n",kk++);
if(n == 1) {
printf(
"The minimal distance is: 0.00\n");
}
else {
printf(
"The minimal distance is: %.2lf\n",kruskal());
}
cin
>>n;
if(n) puts("");
}
}

  WA了几次

1、没考虑到这个题,如果给n=1的时候输出0.00

2、cnt 计数器放在了  if 判断外面

3、一开是用了一个极复杂的方法判断合并次数,而且合并的时候出错了