uestc oj 1223 Islands

Islands

这一题利用逆向思维+并查集  水位是连续的自然数

显然题目是要求在不同水位情况下的不同子集个数 显然在水位降低的时候子集的个数是有上一个水位的情况
改变而来,所以可以利用上一次的数据
为简化计算从而使每个节点只计算一次,可以首先进行排序。
先建立结构体存放节点数据  行r 列 c 以及 高度 h 读入数据的同时进行初始化
每个节点的父亲初始化为自身 
按照高度h对节点进行排序   
然后   按照水位逆序查询,首先求ans[i](i为所求最高水位)的子集个数
过程如下  从islans最高楼房高度开始  每次读入一个高度高于 ans[i]的楼房就ans[i]++
后面对楼房的四邻进行查询,如果高度仍高于ans[i] 且与其不是同一子集就ans[i]--  并且进行合并
这样的话  就避免了重复比如一个子集有3个相邻(111模式)的楼房构成  然后每次读入都加了1 共计3 
然后在读入左边1的时候(查询四周)中间的1并入子集 并ans[i]--  再读入中间1的时候由于与左边的1已经属于同一集合
所以不用减1 而右面的1并入集合 ans[i]--   然后再读入右边1的时候不会出现--情况因为三者都是同一集合了
最后得出正确答案  1个集合 
其余情况 同理可得 每次低水位ans[--i]利用高水位ans[i]时候的数据再继续读入楼房高度(高于低水位的数据不用再次读入)因为再次读入结果仍会是ans[i];
最后得出结论;
说的不是很明白 ,较难表达 望见谅!

时间复杂度:集合的合并算法很简单,只要将两棵树的根结点相连即可,这步操作只要O(1)时间复杂度
采用路径压缩之后,查找的时间复杂度也降低为了O(1) 这个题目还进行了排序  额O(n^2)?
那么总体就是O(n^2+1)
空间复杂度  O(n)


#include
#include
#include
#define MAX 1000010
using namespace std;  //只有在添加了名字空间之后才能真正调用 sort函数
int d[4][2]={0,1,0,-1,-1,0,1,0};  //  按照上下左右的方向进行搜素  以判别出是否属于同一集合
int T,n,m,i,j,k,s;
struct node
{
    int r,c;
    int h;
}num[MAX];
int father[MAX],h[MAX],ans[MAX],que[MAX];


bool cmp(node a,node b) 
{
   return a.h0&&c>0&&r<=n&&c<=m) return true;
    else
    return false;
}


void deal()
{
    for(i=n*m,j=k;j>=1;j--)//i代表总结点个数(已经排序)
    {
        ans[j]=ans[j+1];    //j代表水位
        for(;que[j]

其实并查集的那个findFather操作就是一个递归的很简单的,不用想的太多的。

你可能感兴趣的:(数据结构--并查集)