【百度之星初赛A】1002 数据分割(并查集+Set)

来源:互联网 发布:unity3d 微信登录 ios 编辑:程序博客网 时间:2024/06/05 14:06

在比赛的时候直接想到的就是用并查集加Set的做法,但是由于评测爆炸,只交了一发还没有过。赛后有好好想了之前的思路,还参考了一些博客,发现这种做法的确可以AC。


题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6109


分析:

如果两个元素是相等的那就将它们合并到一起,同时用Set记录不相等的数,开一个Set数组,Set[i]表示与i不相等的数。因此相连的都是相等的,集合中的都是不等的。

如果e = 1, 那就找a, b的根节点fa, fb,如果在Set[fa]中找到fb 或者 在Set[fb]中找到fa, 那就说明存在矛盾,就从这里截断。如果没有矛盾,那就判断两个是不是同根,如果不同根就合并两个集合,并且更新相关的Set[i]

如果e = 0, 先把fa加到Set[fb]中, fb加到Set[fa]中,然后判断两个是不是同根,如果同根就有矛盾。

就这样就可以完成数据分割。

同时,还看到了一个初始化的技巧,就是将所有出现的数字,用Set记录,当出现矛盾,要开始下一组时只需要将Set中的每一个元素对应的Set和数组置位就可以了。


代码:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <map>#include <set>#include <vector>#include <queue>#include <cmath>#include <bitset>using namespace std;const int MAXN = 100005;int fa[MAXN];set<int> Set[MAXN], con;int re[MAXN];int find(int x){    if(fa[x] == -1) return x;    return fa[x] = find(fa[x]);}void unit(int x, int y){    x = find(x);    y = find(y);    if(x != y) fa[x] = y;}int main(){    int L;    re[0] = 0;    int cnt = 0;    scanf("%d", &L);    int i, j, e;    memset(fa, -1, sizeof(fa));    while(L--)    {        scanf("%d%d%d", &i, &j, &e);        con.insert(i), con.insert(j);        int ri = find(i), rj = find(j);        cnt += 1;        if(e == 1)        {            if(Set[ri].count(rj) || Set[rj].count(ri))            {                re[++re[0]] = cnt;                cnt = 0;                for(auto e : con)                {                    Set[e].clear();                    fa[e] = -1;                }                con.clear();            }            else if(ri != rj)            {                fa[ri] = rj;                for(auto e : Set[ri])                {                    Set[rj].insert(e);                    Set[e].erase(ri);                    Set[e].insert(rj);                }                Set[ri].clear();            }        }        else        {            Set[ri].insert(rj), Set[rj].insert(ri);            if(ri == rj)            {                re[++re[0]] = cnt;                cnt = 0;                for(auto e : con)                {                    Set[e].clear();                    fa[e] = -1;                }                con.clear();            }        }    }    for(int i = 0; i <= re[0]; ++i)        printf("%d\n", re[i]);    return 0;}


阅读全文
0 0
原创粉丝点击