hdu6109 数据分割(并查集+set)

题目:hdu6109
思路:每输入一行合并一下,如何产生矛盾则说明该行为后为分隔符。
合并用并查集,同时还需要一个维护一个set来存储不等条件之间的关系。
利用两个数组flag 和flag2来作为并查集和set的“脏位”。
代码如下:

#include <cstdio>
#include <algorithm>
#include <set>

using namespace std;


const int maxn = (int)1e5 + 10;
int flag[maxn], flag2[maxn];
int fa[maxn];
int cnt, ans[maxn], indx;
set<int> S[maxn];
set<int> :: iterator it;


int find(int x) {
    if (flag[x] != indx) {
    flag[x] = indx;
    fa[x] = x;
    }
    return fa[x] != x ? fa[x] = find(fa[x]) : x;

}

bool unit(int r1, int r2) {
    if (S[r1].size() < S[r2].size())
    swap(r1, r2);
    if (r1 == r2) return true;
    for (it = S[r2].begin(); it != S[r2].end(); it ++) {
    if (find(*it) == r1) return false;
    S[r1].insert(find(*it));
    }
    fa[r2] = r1;
    return true;

}

int main(){
    freopen("a.in", "r", stdin);
    freopen("a.out", "w", stdout);

    indx ++;
    int L; scanf("%d", &L);

    while (L--) {
    int u, v, e;
    scanf("%d %d %d", &u, &v, &e);

    ans[cnt] ++;

    int r1 = find(u), r2 = find(v);

    if (flag2[r1] != indx) {
        flag2[r1] = indx;
        S[r1].clear();
    }

    if (flag2[r2] != indx) {
        flag2[r2] = indx;
        S[r2].clear();
    }

    if (e) {
        if (!unit(r1, r2)) { indx ++; cnt ++;}

    }
    else {
        if (r1 == r2) {indx ++; cnt ++;}
        else {
        S[r1].insert(r2);
        S[r2].insert(r1);
        }
    }



    }
    printf("%d\n", cnt);
    for (int i = 0; i < cnt; i ++) printf("%d\n", ans[i]);


    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37577390/article/details/81144057