ZOJ 1203 - Swordfish

来源:互联网 发布:矩阵qr分解例题 编辑:程序博客网 时间:2024/04/30 15:53

并查集 - Kruskal

第一次敲并查集,裸题,很好过。

 

 

 

题意:有n个城市,每个城市有它的坐标,连接这n个城市所需的线路长度的最小值。

 

分析:在本题中,任意两个点之间都有边连通,其权值是两城市之间的距离,将边存入edge[]数组里,用Kruskal求解。

 

AC代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#define MAXN 105#define MAXM 5000struct Edge  //边{    int u, v;    double w;}e[MAXM];int p[MAXM];  //p[i]为节点i在集合中对应的树中的根节点double x[MAXN], y[MAXN];  //城市坐标int n, m;  //点,边个数double sum;  //权值和int Find(int x)  //找x所在集合的根节点{    int s;    for(s=x; p[s]>=0; s=p[s])    while(s!=x)    {        int tmp = p[x];        p[x] = s;        x = tmp;    }    return s;}void Union(int R1, int R2)  //合并{    int r1 = Find(R1);    int r2 = Find(R2);    int tmp = p[r1] + p[r2];    if(p[r1] > p[r2])    {        p[r1] = r2;        p[r2] = tmp;    }    else    {        p[r2] = r1;        p[r1] = tmp;    }}int cmp(const struct Edge *a, const struct Edge *b){    if(a->w > b->w) return 1;    else return -1;}void Kruskal(){    int num = 0;    int u, v, i;    memset(p, -1, sizeof(p));    for(i=0; i<m; i++)    {        u = e[i].u;        v = e[i].v;        if(Find(u) != Find(v))        {            sum += e[i].w;            num++;            Union(u, v);        }    }}int main(){    int t = 1;    while(scanf("%d",&n),n)    {        int i,j;        double d;        for(i=0; i<n; i++)        {            scanf("%lf%lf",&x[i],&y[i]);        }        int mm = 0;        for(i=0; i<n; i++)  //更新edge数组            for(j=i+1; j<n; j++)            {                d = sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) );                e[mm].u = i;                e[mm].v = j;                e[mm].w = d;                mm++;            }        m = mm;        qsort(e, m, sizeof(e[0]), cmp);  //边的权值按从小到大排列        sum = 0.0;        Kruskal();        if(t>1) printf("\n");        printf("Case #%d:\n", t);        printf("The minimal distance is: %.2lf\n", sum);        t++;    }    return 0;}


 

 

 

 

原创粉丝点击