zoukankan      html  css  js  c++  java
  • HDU 1232 畅通工程(并查集分析)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1232

    并查集,大一没学数据结构,所以把这道题放了一段时间,当时百度了好多并查集的资料,还是没弄明白,今天看到有人传了个数据结构的PPT.。就下载下来看了下并查集的部分。正好在这里写下分析:

    根据我的理解,并查集就是维护了几个动态的集合,集合中的每一个元素都标记了一个父节点,同一个集合的代表是相同的。当一个元素的父节点就是他本身时,它就是该集合的代表。

    并查集有三种操作:

    1>make(x).用于初始化集合,将每个元素的父节点设置为他本身。即表示当前一个元素为一个集合,互相没有联系

    2>union(x,y)合并x,和y所在的集合。即把y的代表设置为x所在集合的代表。

    3>find(x),;返回x所在集合的代表

    这里用数组实现,int father[i]....其中i表示元素,father[i]的值指向它的父节点。

    根据代表的父节点就是他本身这个特点,找出一个元素的代表:

    int find(int x)                  //用非递归的实现
      {
          while (father[x] != x) x = father[x];
          return x;
      }
    int find(int x)                   //用递归的实现
      {
          if (father[x] != x) return find(father[x]);
          else return x;
      } 


    合并,即把一个元素所在集合的代表的父节点 设置为 另一个元素所在集合的代表:

    void combine(int a,int b)   //合并
    {
    	int ta=find(a);
    	int tb=find(b);
    
    	if(ta!=tb)
    		father[ta]=tb;
    }


     

    所以,根据并查集判断两个元素是否有联系,只需判断他们是否在同一个集合里即可,也就是判断他们的代表是不是同一个

    没有经过任何优化.................

    AC代码:

    #include<iostream>
    using namespace std;
    
    const int MAX=1000;
    int father[MAX];
    
    void make(int n)    //初始化
    {
    	for(int i=1;i<=n;i++)
    		father[i]=i;
    }
    
    int find(int x)    //查找
    {
    	while(father[x]!=x)
    		x=father[x];
    
    	return x;
    }
    
    void combine(int a,int b)   //合并
    {
    	int ta=find(a);
    	int tb=find(b);
    
    	if(ta!=tb)
    		father[ta]=tb;
    }
    
    int main()
    {
    	int i,n,m,a,b,tmp;
    
    	while(cin>>n,n)
    	{
    		make(n);
    		cin>>m;
    		for(i=1;i<=m;i++)
    		{
    			cin>>a>>b;
    			combine(a,b);
    		}
    
    		tmp=0;
    		for(i=1;i<=n;i++)   //确定连通分量个数
    			if(father[i]==i)
    				tmp++;
    		
    		cout<<tmp-1<<endl;
    	}
    
    	return 0;
    }


     

  • 相关阅读:
    【BZOJ3218】 a+b Problem
    【BZOJ3993】 星际战争
    【BZOJ3991】 寻宝游戏
    【BZOJ2959】长跑 (LCT+并查集)
    NOIP2017记
    【CF 678F】Lena and Queries
    【Learning】多项式乘法与快速傅里叶变换(FFT)
    Subsequence Count (线段树)
    【留言板】
    【bzoj 4173】数学
  • 原文地址:https://www.cnblogs.com/frankM/p/4399556.html
Copyright © 2011-2022 走看看