zoukankan      html  css  js  c++  java
  • HDU 6109 数据分割(并查集+启发式合并)

    题目链接

    题目大意

      略

    解题思路

      对于相等的关系很好维护,关键是对于不想等的关系。如果(x_i)(x_j)不相等,那么(x_i)所在集合中的所有点都是和(x_j)所在集合中的所有点不相等的。
      把不相等的(x_i)(x_j),所在集合的代表结点建一条边,如果(x_i)所在集合要和其他集合合并,那么在合并的时候指向被合并集合的边都要指向合并的集合,反之,被合并集合指向其他集合的边也要加进合并的集合里头。如果两个合并的集合之间有边,说明关系冲突。

    代码

    #include<set>
    #include<map>
    #include<ctime>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<string>
    #include<vector>
    #include<climits>
    #include<cstring>
    #include<cstdlib>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    #define endl '
    '
    #define clr(arr,b) memset(arr, b, sizeof(arr))
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll, int> P;
    typedef pair<ll, int> Pll;
    const double pi = acos(-1.0);
    const double eps = 1e-8;
    const ll MOD = 1e9+7;
    const int INF = 0x3f3f3f3f;
    const int maxn = 1e5+10;
    const int maxm = 2e6+10;
    struct E {
        int to, nxt;
    } e[maxm]; int h[maxn], tot;
    int l, p[maxn], num[maxn];
    void add(int u, int v) {
        ++num[u];
        e[++tot] = {v, h[u]}; h[u] = tot;
    }
    int find(int x) {
        return p[x]==x?p[x]:p[x]=find(p[x]);
    }
    vector<int> ans, tmp;
    bool merge(int a, int b) {
        if (num[a]>num[b]) swap(a, b);
        num[b] += num[a];
        p[a] = p[b];
        int last = 0;
        for (int i = h[a]; i; i=e[i].nxt) {
            int v = e[i].to;
            if (v==b) return 1;
            e[i^1].to = b;
            last = i;
        }
        if (last) {
            e[last].nxt = h[b];
            h[b] = h[a];
        }
        return 0;
    }
    void solve() {
        ans.push_back(tmp.size()/2); tot = 1;
        for (auto i : tmp) p[i] = i, h[i] = 0, num[i] = 0;
        tmp.clear();
    }
    int main() {
        cin >> l; tot = 1;
        for (int i = 0; i<=l; ++i) p[i] = i, num[i] = 0, h[i] = 0;
        for (int i = 0, a, b, c; i<l; ++i) {
            scanf("%d%d%d", &a, &b, &c);
            tmp.push_back(a), tmp.push_back(b);
            if (c) {
                if (find(a)!=find(b) && merge(find(a), find(b))) solve();
            }
            else {
                if (find(a)==find(b)) solve();
                else add(find(a), find(b)), add(find(b), find(a));
            }
        }
        cout << ans.size() << endl;
        for (auto v : ans) printf("%d
    ", v);
        return 0;  
    }
    
  • 相关阅读:
    java反射机制
    java的hashmap与hashtable说明,简单易理解
    awk
    python的w+到底是什么
    hive深入浅出
    【OpenCV新手教程之十五】水漫金山:OpenCV漫水填充算法(Floodfill)
    对你相同重要的非技术贴,10件事证明你跟错了人
    SVM中为何间隔边界的值为正负1
    pushlet服务端推送——多播
    谁洗碗,搭载我的技术目标,起航。
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/13797981.html
Copyright © 2011-2022 走看看