题目: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;
}