关闭

[置顶] 并查集解决最优灌溉问题(最小生成树问题)

标签: 数据结构最小生成树最优灌溉
58人阅读 评论(0) 收藏 举报
分类:

以下都是个人理解,解释别人写好的代码,随便写写
1.什么是并查集
是一种数据结构,其实也就是一种树结构
把i节点的父节点保存在array[i]数组里,根节点的父节点为自身。
对于这种数据结构可以实现的功能有两个
(1)查找一个节点的根节点,通过数组里保存的父节点一层一层向上查找,知道找到一个节点的父节点是自己,那这个节点就是根节点了。
(2)判断两个节点是否属于一个树,找到这两个节点的根节点进行比较,如果根节点相同,这两个节点就属于一个树,如果不相同,就不属于一个树。
(3)把两个树合并,在功能(2)中如果判断出两个节点不属于一个树,想要把这两个树合并,就把其中一个节点的根节点的父节点从自身变更为另一个节点的根节点,就可以实现两个树的合并,即并集。
2.最优灌溉问题
本质都一样,求最小生成树
3.代码实现

# include <iostream>
# include <algorithm>
using namespace std;
struct vex  //水渠结构体数组
{
    int i,j,a;
};
int node[100];   //并查集的节点数组,值代表当前节点的父节点
bool comp(vex a,vex b) //自定义比较函数
{
    return a.a<b.a;
}
int find( int a) //并查集的查询算法
{
    return node[a] == a ? a : find(node[a]);
}
int main()
{
    int m,n;//m代表麦田数量   n代表可建立的水渠数量
    scanf("%d %d",&m,&n);
    vex v[100];
    for(int i =0;i<n;i++)
    {
        scanf("%d %d %d",&v[i].i,&v[i].j,&v[i].a); //输入每一条可建造的水渠的数据
    }
    for(int i=0;i<m;i++)
    {
        node[i] = i;  //初始化每个麦田所在树结构的根节点为自身
    }
    sort(v,v+m,comp);//先根据每条水渠的花费对水渠结构体数组进行排序 从小到大
    int num = 0;//  记录最终花费
    int bian = 0; //记录当前建造的水渠数量
    for(int i = 0;bian < m-1;i++) 
    {
        if(find(v[i].i) != find(v[i].j)) //如果父节点不相同,说明该两个麦田不在一个树中,则把该两个节点合并到一个树中,即使父节点相同,
        {                                                                       //建造这两个麦田之间的水渠,因为已经过排序,所以是当前花费最少的一个水渠   
            num+=v[i].a; //增加花费                                    如果两个麦田的根节点相同,说明这两个麦田以通水田,不需要再建立,则跳过该条水渠的建立
            bian++; //增加水渠数量
            node[v[i].j] = find(v[i].i); //使v[j].j节点的根节点 = v[i].i节点的根节点
            printf("%d --- %d     %d\n",v[i].i,v[i].j,v[i].a);  //打印出当前建造的水渠的起始于结束节点与花费
        }
    }
    printf("最少花费:   %d",num);
    return 0;
}

这里面用到了sort函数,是algorithm库里自带的一个排序函数。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:3675次
    • 积分:322
    • 等级:
    • 排名:千里之外
    • 原创:29篇
    • 转载:0篇
    • 译文:0篇
    • 评论:1条
    最新评论