找一个以前做过的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、一开是用了一个极复杂的方法判断合并次数,而且合并的时候出错了