P1546 最短网络 Agri-Net题解(克鲁斯卡尔)

P1546 最短网络 Agri-Net

 那么这个题是一道最小生成树的板子题

在此讲解kruskal克鲁斯卡尔方法;

原理:

并查集在这里被用到;

众所周知:树满足这样一个定理:如果 图 中有n个节点并且相联通,那么找出n-1条连接所有节点的边并且使连接成的图中没有环(走一圈又回到原先节点的路径),那么这个图一定是一棵树。

那么,我们写代码时只要满足以上条件并且使得找到的n-1条边总和最小,那么这棵树就是最小生成树啦!QWQ。

那么,我们将每个点都看成一个集合,每个集合的初始值为这个点的编号,保证每个集合的值都不相同,从邻接矩阵(原谅本超级蒟蒻不会链式前向星)中用二重循环找出权值最小的边,将这条边连接的两个点所在的集合搞成一个集合(并查集操作),将集合的统一数值设为第一个点(始点)的集合的值,即将这两个集合加入生成树中,再用判断这两个点的集合的值是不是相同(是不是一个环)来决定是否加入树就行了。。

(放松一下手指。)

最后在双重循环中加入最外层循环int k=1;k<=n-1;k++来找n-1条边,就 AC

安利两个英语单词:矩阵matrix,联通connected

上代码:

#include<cstdio>//matrix为矩阵 
#include<iostream>
#include<algorithm>
using namespace std;
int n,matrix[81][81],connect[81],i0,j0,sum=0,t;//matrix为输入的数字矩阵,connect为每个点所属的连通图,sum为最小边权值之和
int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&matrix[i][j]);//以上4行为输入操作 for(int i=1;i<=n;i++) connect[i]=i;//连通图初始化 for(int k=1;k<n;k++)//n-1条边 { int minn=2147000000;//倒也可以是2147483647 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(matrix[i][j]&&connect[i]!=connect[j]&&matrix[i][j]<minn) { minn=matrix[i][j]; i0=i;j0=j;//存下这个边的始点和终点 } sum+=minn;//加入权值之和 t=connect[j0]; for(int i=1;i<=n;i++) if(connect[i]==t)connect[i]=connect[i0];//找到集合中的元素(因为不止有一个所以for),将第二个集合合并到第一个中成为一个大的 } printf("%d",sum);//输出最小权值之和(题目中为最小费用) return 0; }

 我这个不是标准的并查集查找方式,标准的请详见我的博客https://www.cnblogs.com/lbssxz/p/10753073.html

完。。结。。QAQ

posted @ 2019-04-22 19:54  李白莘莘学子  阅读(299)  评论(0编辑  收藏  举报