Kruskal算法例题

来源:互联网 发布:中美军事差距知乎 编辑:程序博客网 时间:2024/06/03 03:40

例题一:剑鱼行动(Swordfish).

题目描述:给定平面上N个城市的坐标,计算连接这n个城市所需线路长度的最小值。

输出描述:如下图所示,每两个测试数据的输出之间输出一个空行

#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#include<stdlib.h>using namespace std;#define MAXN 110#define MAXM 5000struct edge{    int u,v;    double w;}edges[MAXN];int parent[MAXN];int n,m;double x[MAXN],y[MAXN];///每个顶点x坐标和y坐标int i,j;double sumweight;void UFset(){    for(i=0;i<n;i++)        parent[i]=-1;}int Find(int x){    int s;    for(s=x;parent[s]>=0;s=parent[s]);    while(s!=x)///压缩路径    {        int temp=parent[x];        parent[x]=s;        x=temp;    }    return s;}void Union(int R1,int R2){   int r1=Find(R1);   int r2=Find(R2);   int temp=parent[r1]+parent[r2];   if(parent[r1]>parent[r2])///加权法则   {       parent[r1]=r2;       parent[r2]=temp;   }   else   {       parent[r2]=r1;       parent[r1]=temp;   } } int cmp(const void *a,const void *b) {     edge aa=*(const edge *)a;     edge bb=*(const edge *)b;     if(aa.w>bb.w) return 1;     else        return -1; } void Kruskal() {     int num=0;     int u,v;     UFset();     for(i=0;i<m;i++)     {         u=edges[i].u;         v=edges[i].v;         if(Find(u)!=Find(v))         {             sumweight+=edges[i].w;             num++;             Union(u,v);         }         if(num>=n-1)            break;     } } int main() {     double d;     int kase=1;     while(scanf("%d",&n)!=EOF)     {         if(n==0) break;         for(i=0;i<n;i++)            scanf("%lf%lf",&x[i],&y[i]);            int mi=0;///记录边的数目         for(i=0;i<n;i++)///任意两个顶点间的距离,有意思            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]));             edges[mi].u=i;             edges[mi].v=j;             edges[mi].w=d;             mi++;         }         m=mi;         qsort(edges,m,sizeof(edges[0]),cmp);///快速排序         sumweight=0.0;         Kruskal();         if(kase>1)///第一组测试数据前有空格            {                printf("\n");                 getchar();            }         printf("Case #%d:\n",kase);         printf("The minimum distance is: %0.2f\n",sumweight);         kase++;     }     return 0; }

测试数据:


例题二:网络(Network)

先输入顶点和边,然后是每条边的起始点和边的权值

输出描述:首先输出最长的单根网线的长度。然后输出设计方案:先输入一个整数p,代表所使用的网线的数目,然后输出p对顶点,表示每对网线所连接的集线器的编号

#include<cstdio>#include<iostream>#include<cstring>#include<stdlib.h>using namespace std;#define MAXN 1005#define MAXM 15005struct edge{    int u,v,w; }edges[MAXM]; int parent[MAXN]; int ans[MAXN],ai;///存储的是依次选择的边的序号;数组ans的下标 int n,m; int num,maxedge;///最长的边 int i,j; void UFset() {     for(i=0;i<n;i++)        parent[i]=-1; } int find(int x) {     int s=x;     for(s=x;parent[s]>=0;s=parent[s]);     while(s!=x)///压缩路径     {         int temp=parent[x];         parent[x]=s;         x=temp;     }     return s; } void Union(int R1,int R2) {     int r1=find(R1);     int r2=find(R2);     int temp=parent[r1]+parent[r2];     if(parent[r1]>parent[r2])///加权法则     {         parent[r1]=r2;         parent[r2]=temp;     }     else     {         parent[r2]=r1;         parent[r1]=temp;     } } int cmp(const void *a,const void *b) {     edge aa=*(const edge *)a;     edge bb=*(const edge *)b;     return aa.w-bb.w; } void Kruskal() {     ai=0;     num=0;     maxedge=0;     int u,v;     UFset();     for(i=0;i<m;i++)     {         u=edges[i].u;         v=edges[i].v;         if(find(u)!=find(v))         {             ans[ai]=i;             ai++;             if(edges[i].w>maxedge)                maxedge=edges[i].w;             num++;             Union(u,v);         }         if(num>=n-1)            break;     } } int main() {     int i,j;     while(scanf("%d%d",&n,&m)!=EOF)     {         for(i=0;i<m;i++)            scanf("%d%d%d",&edges[i].u,&edges[i].v,&edges[i].w);         qsort(edges,m,sizeof(edges[0]),cmp);         Kruskal();         printf("%d\n",maxedge);         printf("%d\n",num);         for(i=0;i<num;i++)///ans[]存储的是依次选择的边的序号            printf("%d %d\n",edges[ans[i]].u,edges[ans[i]].v);     }     return 0; }




0 0