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;  
}
原文地址:https://www.cnblogs.com/shuitiangong/p/13797981.html