显然,维护xi=xj的情况,并查集即可
而xi!=xj时,可以开一个1e5的set<int>数组,记录xi不等于的数
xi=xj约束
①检查是否满足xi!=xj : 遍历较小的set的元素t,满足un.find(t)==un.find(xi)则不成立 | {un为并查集}
②合并并查集的同时,启发式合并set
所有合并的总操作次数=L个叶子的满二叉树节点个数,最坏情况下O(n∗log(n)∗log(n))
xi!=xj约束
①检查xi与xj是否在同一个并查集内即可
②更新set[un.find(xi)].insert(xj),set[un.find(xj)].insert(xi),O(logn)
#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std;
const int N = 100000 + 5;
const double EPS = 1e-7;
struct S{
int same[N];
set<int>unSame[N];
void init(int n){
for(int i=0;i<=n;++i){
unSame[i].clear();
same[i]=i;
}
}
void init(set<int>&t){
initSame(t);
initUnSame(t);
}
void initSame(set<int>&t){
for(int x:t){
same[x]=x;
}
}
void initUnSame(set<int>&t){
for(int x:t){
unSame[x].clear();
}
}
int find(int x){
return x==same[x]?x:(same[x]=find(same[x]));
}
bool isSame(int x,int y){
x=find(x);
y=find(y);
return same[x]==same[y];
}
bool isUnSame(int x,int y){
x=find(x),y=find(y);
/*return (unSame[x].find(y)!=unSame[x].end()||
unSame[y].find(x)!=unSame[y].end());*/
set<int>&big=unSame[x];
set<int>&small=unSame[y];
if(big.size()<small.size()){
swap(big,small);
swap(x,y);
}
for(int t:small){
if(x==find(t)){
return true;
}
}
return false;
}
void merge(int x,int y){
x=find(x);
y=find(y);
same[max(x,y)]=min(x,y);
set<int>&big=unSame[x];
set<int>&small=unSame[y];
if(big.size()<small.size()){
swap(big,small);
swap(x,y);
}
for(int t:small){
big.insert(find(t));
}
small.clear();
swap(unSame[find(x)],big);
}
void setXunSameY(int x,int y){
x=find(x);
y=find(y);
unSame[x].insert(y);
unSame[y].insert(x);
}
}s;
set<int>appear;
void slove(int n){
s.init(n);
vector<int>ans;
appear.clear();
int num=0;
for(int i=0;i<n;++i){
int x,y,e;
scanf("%d%d%d",&x,&y,&e);
x=s.find(x),y=s.find(y);
appear.insert(x);
appear.insert(y);
++num;
if(e){//x==y
if(s.isUnSame(x,y)){
ans.push_back(num);
num=0;
s.init(appear);
}
else{
s.merge(x,y);
}
}
else{
if(s.isSame(x,y)){
ans.push_back(num);
num=0;
s.init(appear);
}
else{
s.setXunSameY(x,y);
}
}
}
printf("%d\n",ans.size());
for(int t:ans){
printf("%d\n",t);
}
}
int main()
{
//freopen("/home/lu/code/r.txt","r",stdin);
//freopen("/home/lu/code/w.txt","w",stdout);
int n;
while(~scanf("%d",&n)){
slove(n);
}
return 0;
}

11万+

被折叠的 条评论
为什么被折叠?



