并查集详解_兼_hdu_1232_畅通工程

10 篇文章 0 订阅
3 篇文章 0 订阅

并查集是一个非常巧妙的数据结构,将一系列输入的数据划分为多个不同的部分,从而进行相应的后续处理。

自己在学习并查集之前也实现过这种类型,不过没有进行压缩,时间复杂度很大。

对于并查集的讲解,试着自己给自己讲一遍,觉得自己的理解还是挺清楚的,但要写博文的话实在太费时间了,暂时放弃。

推荐大家看并查集讲解,作者的代码写的非常清楚,讲解也很有趣。


传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1232

类似的还有:http://acm.hdu.edu.cn/showproblem.php?pid=1213

值得一提的是,最后必须用mark[find(i)而不是mark[pre[i]],因为并查集有时候不会被压缩。比如:1 2,2 3,对比1 2,2 3,1 4.

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;
const int maxn=1000;
int mark[maxn];
int pre[maxn];
int find(int x)
{
    int r=x;
    while(r!=pre[r])
        r=pre[r];

    int i=x,j;
   // while(i!=r)
      while(pre[i]!=r) 
    {
        j=pre[i];
        pre[i]=r;
        i=j;
    }
    return r; //r作为最终的节点
}

void mix(int x,int y)
{
    int fx=find(x),fy=find(y);
    if(fx!=fy) pre[fx]=fy;//pre[fx]=fy也可以。但下面这个语句很显然是错的:fx=pre[fy],太容易疏忽的一个错了
}



int main(void)
{
    int n,m;
    int a,b;
    int i,j,k;
    int T;
    while(cin>>n)
    {
        if(n==0) break;
        for(i=1;i<=n;i++)
            pre[i]=i;
        cin>>m;

        for(i=0;i<m;i++)
        {
           cin>>a>>b;
            mix(a,b);
        }
        //如果一共有n块,那么需要n-1条道路
         memset(mark,0,sizeof(mark));

         for(i=1;i<=n;i++)    //题目中输入的是测试数据,1-n,自己一开始写的是从0开始,所以
                               //测试数据过了但还是WA
            mark[find(i)]=1;
         int cnt=0;
         for(i=1;i<=n;i++)
            if(mark[i]) cnt++;
         cout<<cnt-1<<endl;
       // for(i=0;i<n;i++) cout<<mark[i]<<" ";
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值