1349:【例4-10】最优布线问题

题目描述

题目出处:点这里

在这里插入图片描述

输入格式

在这里插入图片描述

输出格式

在这里插入图片描述

样例

输入
3
0 1 2
1 0 1
2 1 0
输出
2

提示

样例说明

在这里插入图片描述

分析与思路

这个题与我们在介绍Prim算法时所举出的例题的不同之处在于:例题所求的值是最小生成树,而本题所求的是最小生成树各边权之和所以相较于介绍Prim算法时列出的代码,在这个题目当中需要进行一些更改。

更改在哪里

让我们先回顾一下在介绍Prim算法时的代码

vector<Node> Prim(int sid){
	vector<Node>result;
	memset(flag,false,sizeof(flag));
	pque.push(Node(-1,sid,0));
	while(result.size()<n-1){
		Node nd=pque.top();pque.pop();
		if(flag[nd.id])continue;
		flag[nd.id]=true;
	//	if(nd.from!=-1)result.push_back(nd);
		if(nd.id!=sid)result.push_back(nd);
		for(Node df:g){
			if(!flag[df.id]&&df.from==nd.id){//判定时不再需要判断是否存在这条边
			//需要判断这条边是否连接了该顶点和其他定点
				pque.push(Node(nd.id,df.id,df.w));
			}
		}
	}
	return result;
}

在这段代码中,函数的返回值是一个记录了最小生成树的可变长数组,而我们要求的是最小生成树的边权值之和,所以我们应该在寻找最小生成树的时候来统计
,最后再让函数返回统计值做为答案

int Prim(int sid){
	int result=0,sum=0;
	//统计值   记录已经统计了多少条边
	memset(flag,false,sizeof(flag));
	pque.push(Node(-1,sid,0));
	while(sum<n){//当统计的边的数量达到n-1(形成最小生成树)结束循环
		Node nd=pque.top();pque.pop();
		if(flag[nd.id])continue;
		flag[nd.id]=true;
		sum++;//每次统计边时需要同时增加
	//	if(nd.from!=-1)result.push_back(nd);
		if(sum!=1)result+=nd.w;
		//这里不再是记录树的边,而是记录树的边权总和
		for(int i=1;i<=n;i++){
			if(!flag[i]&&g[nd.id][i]<MXV){
				pque.push(Node(nd.id,i,g[nd.id][i]));
			}
		}
	}
	return result;
}

那么按照这些思路,我们就可以轻松解出这道题了

代码实现

#include<bits/stdc++.h>
using namespace std;

const int MXV=0x3f3f3f3f;
const int MXN=300; 
int n;
int a,b,len;
struct Node{
	int from,id,w;
	Node(){}
	Node(int i,int d,int l){
		from=i;id=d;w=l;
	}
	friend bool operator < (Node a,Node b){
		return a.w>b.w;
	}
};  
bool flag[MXN+1];
priority_queue<Node>pque;
int g[MXN+1][MXN+1];

int Prim(int sid){
	int result=0,sum=0;
	//统计值   记录已经统计了多少条边
	memset(flag,false,sizeof(flag));
	pque.push(Node(-1,sid,0));
	while(sum<n){//当统计的边的数量达到n-1(形成最小生成树)结束循环
		Node nd=pque.top();pque.pop();
		if(flag[nd.id])continue;
		flag[nd.id]=true;
		sum++;//每次统计边时需要同时增加
	//	if(nd.from!=-1)result.push_back(nd);
		if(sum!=1)result+=nd.w;
		//这里不再是记录树的边,而是记录树的边权总和
		for(int i=1;i<=n;i++){
			if(!flag[i]&&g[nd.id][i]<MXV){
				pque.push(Node(nd.id,i,g[nd.id][i]));
			}
		}
	}
	return result;
}

int main(){
	memset(g,0x3f,sizeof(g));
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>len;
			g[i][j]=g[j][i]=len;
		}	
	}
	cout<<Prim(1);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值