C++,电话连线【普里姆算法,最小生成树】

题目描述 Description

一个国家有n个城市。若干个城市之间有电话线连接,现在要增加m条电话线(电话线当然是双向的了),使得任意两个城市之间都直接或间接经过其他城市有电话线连接,你的程序应该能够找出最小费用及其一种连接方案。

 

输入描述  Input Description

    输入文件的第一行是n的值(n<=100).

    第二行至第n+1行是一个n*n的矩阵,第i行第j列的数如果为0表示城市i与城市j有电话线连接,否则为这两个城市之间的连接费用(范围不超过10000)。

 

输出描述  Output Description

       输出文件的第一行为你连接的电话线总数m,第二行至第m+1行为你连接的每条电话线,格式为i j,(i<j), i j是电话线连接的两个城市。输出请按照Prim算法发现每一条边的顺序输出,起始点为1.

       第m+2行是连接这些电话线的总费用。

 

样例输入  Sample Input

5

0 15 27 6 0

15 0 33 19 11

27 33 0 0 17

6 19 0 0 9

0 11 17 9 0

 

样例输出  Sample Output

2

1 4

2 5

17

 

数据范围及提示  Data Size & Hint

n<=100

 

———————————————————————————————————————————————————————————————————————————————————————————

思想:基本的做法和之前写过的普里姆算法求最小生成树的一样,下面写的题解是在那基础之上修改的。

可以戳这个链接先看一下

不同点,更新每个蓝点到白点集团的最小距离时,更新它的father点fa[i]

#include<iostream>
#include<cstring>
using namespace std;

int main(){
    int n,i,j,k,cnt=0,ans=0;
    int e[101][101];//邻接矩阵存边 
    int minn[101];//每个蓝点到白点集团的最小值 
    bool u[101];//标记已加入生成树的点为白点(0),没加入的为蓝点(1) 
    int fa[101];//存白点的father点 
    int que[101];//存有father点的白点,这里往下看就明白了 
    memset(u,1,sizeof(u));//先将所有点标记为蓝点 
    memset(fa,1,sizeof(fa));//将所有点的father点设为起点1 
    memset(minn,0x7f,sizeof(minn));//将所有蓝点到白点集团的最小值初始化为maxint 
    minn[1]=0;//1设为第一个白点 
    
    cin>>n;
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    cin>>e[i][j];
    
    for(i=1;i<=n;i++){
        k=0;
        for(j=1;j<=n;j++)
        if(u[j]&&minn[j]<minn[k]){
            k=j;    
        }//找出当前距离白点集团最近的蓝点 
        u[k]=0;
        ans+=minn[k];
        que[cnt]=k;//把这个点存入输出que里 
        if(minn[k]!=0&&minn[k]!=0x7f) cnt++;//如果当前加入que的点是本来没有连上线的点,才算作新加入的点,cnt++ 
        
        for(j=1;j<=n;j++)
        if(u[j]&&e[k][j]<minn[j]){
            minn[j]=e[k][j];
            if(minn[j]!=0&&minn[j]!=0x7f){
                fa[j]=k;//当一个点的最小值更新的时候,同时更新它的father点 
            } 
        }
    }
    
    cout<<cnt<<endl; 
    for(i=0;i<cnt;i++){
        if(fa[que[i]]<que[i]) cout<<fa[que[i]]<<" "<<que[i]<<endl;
        else cout<<que[i]<<" "<<fa[que[i]]<<endl;
    }
    cout<<ans;
    return 0;
}
View Code

 

 

转载于:https://www.cnblogs.com/guesswhohia/p/6170404.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值