HDU 6109 数据分割 并查集,SET

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

题意:中文题面

解法:每次都贪心地尝试将尽量多的条件放进当前这组,遇到第一个与已有条件冲突时,就是分割的时候。相等具有传递性,直接用并查集维护,不相等的关系用set维护,注意到x1=x2,x1!=x3,x2!=x4,那么有x1!=x4,x2!=x3,所以用并查集合并(x1,x2)的时候,就需要把x1的不等信息合并到x2上。

 

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
namespace DSU{
    int fa[maxn];
    int find_set(int x){
        if(x==fa[x]) return x;
        else return fa[x]=find_set(fa[x]);
    }
};
using namespace DSU;
int n;
set <int> S[maxn];
void init(){
    for(int i=1; i<=n; i++){
        S[i].clear();
        fa[i]=i;
    }
}
int a[maxn], b[maxn], c[maxn];
int ans[maxn];
int main()
{
    while(~scanf("%d", &n))
    {
        init();
        for(int i=1; i<=n; i++){
            scanf("%d %d %d", &a[i],&b[i],&c[i]);
        }
        int cnt = 0;
        for(int i=1; i<=n; i++){
            int u = find_set(a[i]);
            int v = find_set(b[i]);
            if(c[i] == 1){
                if(u==v) continue;
                else if(S[u].find(v)!=S[u].end()){
                    ans[++cnt] = i;
                    init();
                }else{
                    for(set<int>::iterator it=S[v].begin(); it!=S[v].end(); it++){
                        S[u].insert(*it);
                        S[*it].erase(v);
                        S[*it].insert(u);
                    }
                    S[v].clear();
                    fa[v] = u;
                }
            }
            else{
                if(u==v){
                    ans[++cnt]=i;
                    init();
                }else{
                    S[u].insert(v);
                    S[v].insert(u);
                }
            }
        }
        printf("%d\n", cnt);
        for(int i=1; i<=cnt; i++){
            printf("%d\n", ans[i]-ans[i-1]);
        }
    }
    return 0;
}

 

posted @ 2017-08-17 10:15  zxycoder  阅读(291)  评论(0编辑  收藏  举报