Networking(Kruskal)

You are assigned to design network connections between certain points in a wide area. You are given a set of points in the area, and a set of possible routes for the cables that may connect pairs of points. For each possible route between two points, you are given the length of the cable that is needed to connect the points over that route. Note that there may exist many possible routes between two given points. It is assumed that the given possible routes connect (directly or indirectly) each two points in the area.
Your task is to design the network for the area, so that there is a connection (direct or indirect) between every two points (i.e., all the points are interconnected, but not necessarily by a direct cable), and that the total length of the used cable is minimal.
Input
The input file consists of a number of data sets. Each data set defines one required network. The first line of the set contains two integers: the first defines the number P of the given points, and the second the number R of given routes between the points. The following R lines define the given routes between the points, each giving three integer numbers: the first two numbers identify the points, and the third gives the length of the route. The numbers are separated with white spaces. A data set giving only one number P=0 denotes the end of the input. The data sets are separated with an empty line.
The maximal number of points is 50. The maximal length of a given route is 100. The number of possible routes is unlimited. The nodes are identified with integers between 1 and P (inclusive). The routes between two points i and j may be given as i j or as j i.
Output
For each data set, print one number on a separate line that gives the total length of the cable used for the entire designed network.
Sample Input
1 0

2 3
1 2 37
2 1 17
1 2 68

3 7
1 2 19
2 3 11
3 1 7
1 3 5
2 3 89
3 1 91
1 2 32

5 7
1 2 5
2 3 7
2 4 8
4 5 11
3 5 10
1 5 6
4 2 12

0
Sample Output
0
17
16
26

题意:

在多个点之间连线,要使总长度最短,有多组输入

第一行有两个数据P和R,P代表点的总数,R代表有R组两点的距离(P不超过50,R无限制

接下来R行,每行3个数字,前两个代表点的标号,第3个代表两点的距离

思路:、

这属于最短问题,因此是最小生成树问题

但要注意,输入的边关系数量无限制,因此要在输入过程中只把同一两点的距离最短的存放到E数组中,

防止后期筛选过程的超时或者爆栈;

AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node{
    int u,v,w;
}e[150];     //为了方便排序,这里创建结构体来储存边关系
int book[150][150],pre[150];//  book 记录边关系是否存放过 pre 存放父结点
int n,m;   //n 为顶点数  m 为边关系数
int cmp(node a,node b){
    return a.w<b.w;
}
int Find(int x){    //查找根节点
    int r=x;
    while(r!=pre[r])
        r=pre[r];
    int i=x,j;
    while(i!=r){  //压缩路径
        j=pre[i];
        pre[i]=r;
        i=j;
    }
    return r;
}
int mix(int a,int b){    //联合两个节点
    int fa=Find(a),fb=Find(b);
    if(fa!=fb){
        pre[fb]=fa;
        return 1;
    }
    return 0;
}
void init(){     //初始化pre 数组
    int i;
    for(i=0;i<=n;i++)
        pre[i]=i;
}
int main(){
    while(scanf("%d",&n)!=EOF){
            if(n==0) break;
        scanf("%d",&m);
        memset(book,0,sizeof(book));
        int i;
        int a,b,c;
        int cnt=1;//记录不重复的边关系数量
        for(i=1;i<=m;i++){     //读取边关系
            scanf("%d%d%d",&a,&b,&c);//由于m 的大小不限定,因此每条边关系中取最小的存放
            if(book[a][b]==0&&book[b][a]==0){ //如果没出现过,直接存放
                book[a][b]=i; //book 记录此边关系在数组中的位置
                book[b][a]=i;
                e[cnt].u=a;
                e[cnt].v=b;
                e[cnt].w=c;
                cnt++;  
            }
            else{                //如果出现过,判断已经存放的边关系权值与现在的大小
                int k=book[a][b];
                if(c<e[k].w){  //如果权值更小
                    e[k].u=a;    //更新边关系,如果更大,则忽略此边关系
                    e[k].v=b;
                    e[k].w=c;
                    book[a][b]=i;
                    book[b][a]=i;
                }
            }
        }
        sort(e+1,e+cnt,cmp);  //按权值从小到大的顺序排序
        init();
        int sum=0,countt=0; //sum记录权值和  countt记录可行边数 当countt==n 是则找到最小树
        for(i=1;i<=cnt;i++){
            if(mix(e[i].u,e[i].v)){ //如果目前尚不联通,则选用这条边
                countt++;
                sum+=e[i].w;
            }
            if(countt==n-1) break;//直接选用n-1条边后 跳出循环
        }
        printf("%d\n",sum);
    }
return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值