ZOJ1203(最小生成树kruskal算法)Swordfish

来源:互联网 发布:淘宝店如何转让 编辑:程序博客网 时间:2024/05/24 22:42
题目来源:
Zhejiang University Local Contest 2002, Preliminary, ZOJ1203
题目描述:
给定平面上
N 个城市的位置,计算连接这N 个城市所需线路长度总和的最小值。
输入描述:
输入文件中包含多个测试数据。每个测试数据的第
1 行为一个正整数N0N100,代表
你需要连接的城市数目;接下来有
N 行,每行为两个实数X Y-10000X, Y10000,表示
每个城市的
X 坐标和 Y 坐标。输入文件中最后一行为 N = 0,代表输入结束。
输出描述:
对输入文件中每个测试数据,计算连接所有城市所需线路长度总和的最小值。每对城市之间
的线路为连接这两个城市的直线。输出格式为:第
1 行为"Case #n:",其中n 为测试数据的序号,
序号从
1 开始计起;第 2 行为"The minimal distance is: d",其中d 为求得的最小值,精确到小数
点后
2 位有效数字。每两个测试数据的输出之间输出一个空行。
样例输入: 样例输出:
5
0 0
0 1
1 1
1 0
0.5 0.5
0
Case #1:
The minimal distance is: 2.83
分析:
在本题中,任意两个顶点之间都有边连通,权值为这两个顶点之间的距离。将所有边求出并

存储到边的数组 edges[ ]中后,按照Kruskal 算法求解即可。

//kruskal求最小生成树#include<cstdio>#include<iostream>#include<cstring>#include<cmath>#include<algorithm>using namespace std;const int mn=105,mm=10005;struct Edge{    int u,v;    double w;    bool operator<(Edge t)const    {        return w<t.w;    }} edges[mm];int n,tot,f[mn];double x[mn],y[mn];inline double dist(int i,int j){    return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));}int find(int i){    int x=i;    while(f[i]!=i) i=f[i];    return f[x]=i;}int main(){    int kase=0;    while(~scanf("%d",&n)&&n)    {        tot=0;        for(int i=1; i<=n; ++i)            f[i]=i;//并查集初始化        for(int i=1; i<=n; ++i)            scanf("%lf%lf",x+i,y+i);        for(int i=1; i<n; ++i)            for(int j=i+1; j<=n; ++j)                edges[tot++]=(Edge)            {                i,j,dist(i,j)            };        sort(edges,edges+tot);        double ans=0;        int cnt=0;        for(int i=0; i<tot; ++i)        {            int u=edges[i].u,v=edges[i].v;            int fu=find(u),fv=find(v);            if(fu!=fv)            {                f[fu]=fv;//集合合并                ans+=edges[i].w;                cnt++;                if(cnt==n-1) break;//找到了n-1条边            }        }        if(kase) puts("");        printf("Case #%d:\nThe minimal distance is: %.2lf\n",++kase,ans);    }    return 0;}