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;
}

 

转载于:https://www.cnblogs.com/spfa/p/7380170.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值