最小生成树(kruskal算法)和 (Prime算法)

题目描述:

给定平面上N个城市的位置,计算连接这N个城市所需线路长度总和的最小值。

输入描述:

输入文件中包含多个测试数据。每个测试数据的第1行为一个正整数N,0《=N《=100,代表需要连接的城市数目;接下来有N行,每行为两个实数X和Y,-10000《=X,Y《=10000,表示每个城市的X坐标和Y坐标。输入文件中最后一行为N=0,代表输入结束。

输出描述:

对输入文件中每个测试数据,计算连接所有城市所需线路长度总和的最小值。每对城市之间的线路为连接这两个城市的直线。对于求得的值精确到小数点后两位有效数字。

代码:

kryskal算法:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std ;
int  m , n ;
double x[101], y[101], ans;
int pre[5000];
typedef struct 
 {
  int x,y;
double w;
 }node;
 node edge[5000]; 
 
int cmp(node a, node b)     //从小到大排序
{
return a.w<b.w;



int find(int t)         //递归找到其 父节点,即当前顶点属于哪个集合 
{
     return t==pre[t] ?  t:find(pre[t]) ;



void hebing(int x,int y)   //两个不同集合的合并,将y的父节点更新为x;即把两棵树合并为一颗 
{
pre[y]=x ;



void Kruskal() 
{
     int i,j,x1,x2;
for( i = 0 ; i < n;i++)  //初始化,设定 每个顶点都为一个独立的集合,父节点是自己本身 
         pre[i]=i ;
    for( i = 0 ; i<m ; i++ )
{
x1=find(edge[i].x);
x2=find(edge[i].y); 
if(x1!=x2)               //a==b说明边的两个顶点一属于同一颗树, //将a的父节点更新为b,从而将树a,b合并成一棵树
 {
  hebing(x1,x2); 
  ans += edge[i].w;      //将边的权值加到ans当中
 } 

}     
}


int main()
{
    int T = 0;
    while(scanf("%d", &n), n) {
        ans = 0;
        for(int i = 0; i < n; i++) {
            scanf("%lf %lf", &x[i], &y[i]);
        }
        m = 0;ans=0;
        for(int i = 0; i < n; i++) {
            for(int j = i+1; j < n; j++) {
                edge[m].x = i;
                edge[m].y = j;
                edge[m].w = sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
                m++;
            }
        }
        sort(edge,edge+m,cmp);        
        Kruskal();
        if( T ) printf("\n");
        printf("Case #%d:\n", ++T);
        printf("The minimal distance is: %.2lf\n", ans);
    }
    return 0;
}


Prim算法:

  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3. #include<math.h>  
  4. #include<string.h>  
  5. const double INF = 99999999;  
  6. double dist[101];  
  7. double mat[101][101];  
  8. int flag[101];  
  9. struct point  
  10. {  
  11.     double x,y;  
  12. } a[101],t;  
  13. int main(void)  
  14. {  
  15.     int n,i,j,now,start=1;  
  16.     double min,sum;  
  17.     while( scanf("%d",&n) && n )  
  18.     {  
  19.         for( i = 1; i <= n; i++ )  
  20.             scanf("%lf%lf",&a[i].x,&a[i].y);  
  21.         for( i = 1; i <= n; i++ )  
  22.             for( j = 1; j <= n; j++ )  
  23.             {  
  24.                 if( i==j ) mat[i][j] = 0;  
  25.                 else                             //用邻街矩阵保存边的取值
  26.                 {  
  27.                     mat[i][j] = sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)  
  28.                                             +(a[i].y-a[j].y)*(a[i].y-a[j].y));  
  29.                 }  
  30.             }  
  31.         for( i = 1; i <= n; i++)     
  32.         {  
  33.             dist[i] = INF;  
  34.             flag[i] = 0;  
  35.         }  
  36.         dist[now=1] = 0;  
  37.         flag[1] =1;         //标记节点是否放入集合
  38.         for( i= 1,sum=0; i <n ;i++)  
  39.         {  
  40.             for( j = 1; j <= n; j++)      //入选的节点更新未入选的节点
  41.                 if( !flag[j] && dist[j] > mat[now][j] )    //mat[now][j] 课理解为now点到J点的权值                                                      dist[j] = mat[now][j];  
  42.             for( j = 1,min = INF; j <= n; j++)     //选出最小的边的权值的节点
  43.                 if( !flag[j] && dist[j] < min )  
  44.                     min = dist[now = j];  
  45.             flag[now]=1;                    //标记节点已加入集合
  46.             sum += min;  
  47.         }  
  48.         if( start == 1) printf("Case #%d:/n",start++);  
  49.         else printf("/nCase #%d:/n",start++);  
  50.         printf("The minimal distance is: %.2lf/n",sum);  
  51.     }  
  52.     return 0;  
  53. }  








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值