并查集回顾

今天做了一些欧拉函数和并查集得题目,总感觉这两天很没有状态啊,效率非常低下,希望早点恢复吧~~毕竟选拔赛马上就要到了

因为状态原因,没有耐下心来去啃一道难题,也没有去学习新的知识点,复习了一下并查集

POJ1611

我一开使嘛,用很常规的思路去做,每一个组得老大为最后一个给出的人,然后我尝试再find函数进行时,减少结点得长度(分级)就是让这条线上的都直接连在老大后面,左后判断每一个结点是不是0得老大,TLE!!!

想了又想,空间换时间,加了一个vis数组,没有出现的都直接过,500ms,一看别人提交的0ms,emmmm,时间差的不是一点半点,0ms一般是再基础得输入数据时进行处理,最后可以直接输出答案,很好,空间换时间,我定义一个sum数组,存储root对应得字节点数量,初始化均为1,放到join数组里面,没实现一个老大合并,就根性sum数组,最后100+ms,凑合吧~~,不再管了,去学学python去吧,换换脑子

include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
const int maxn = 3e4 + 3e3;

int pre[maxn];
int vis[maxn];
int s[maxn];

void init(int n)
{
    for(int i = 0;i <= maxn;i++)
    {
        pre[i] = i;
        s[i] = 1;
    }
    memset(vis,0,sizeof(vis));

}
int Find(int x)
{
    return x == pre[x] ? x : x = Find(pre[x]);
}
void join(int a,int b)
{
    int u = Find(a);
    int v = Find(b);
    if(u != v)
    {
        pre[u] = v;
        s[v] += s[u];
    }
}
int main()
{
    int n,m,num,a,b;
    while(~scanf("%d%d",&n,&m))
    {
        if(n == 0 && m == 0)break;
        init(n);
        int ret = 0;
        vis[0] = 1;
        while(m--)
        {
            scanf("%d",&num);
            num--;
            scanf("%d",&a);
            vis[a] = 1;
            while(num--)
            {
                scanf("%d",&b);
                vis[b] = 1;

                join(a,b);
                a = b;
            }

        }
        int ed = Find(0);
//        for(int i = 0;i < n;i++)
//        {
//            if(!vis[i])continue;
//            if(i == pre[i] && pre[i] == ed)
//            {
//                ret++;
//            }
//            else if(Find(i) == ed)
//            {
//                ret++;
//            }
//        }
    //        printf("%d\n",ret);
    printf("%d\n",s[ed]);
    }
    return 0;
}

 ——————————————————————————————————————————————————

明天会更好!加油!!

 

posted @ 2018-03-18 20:53  Butterflier  阅读(149)  评论(0编辑  收藏  举报