HDU 6109 数据分割(并查集+set)
数据分割
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2457 Accepted Submission(s): 748
Problem Description
小w来到百度之星的赛场上,准备开始实现一个程序自动分析系统。
这个程序接受一些形如xi=xj 或 xi≠xj 的相等/不等约束条件作为输入,判定是否可以通过给每个 w 赋适当的值,来满足这些条件。
输入包含多组数据。
然而粗心的小w不幸地把每组数据之间的分隔符删掉了。
他只知道每组数据都是不可满足的,且若把每组数据的最后一个约束条件去掉,则该组数据是可满足的。
请帮助他恢复这些分隔符。
这个程序接受一些形如xi=xj 或 xi≠xj 的相等/不等约束条件作为输入,判定是否可以通过给每个 w 赋适当的值,来满足这些条件。
输入包含多组数据。
然而粗心的小w不幸地把每组数据之间的分隔符删掉了。
他只知道每组数据都是不可满足的,且若把每组数据的最后一个约束条件去掉,则该组数据是可满足的。
请帮助他恢复这些分隔符。
Input
第1行:一个数字L,表示后面输入的总行数。
之后L行,每行包含三个整数,i,j,e,描述一个相等/不等的约束条件,若e=1,则该约束条件为xi=xj ,若e=0,则该约束条件为 xi≠xj 。
i,j,L≤100000
xi,xj≤
之后L行,每行包含三个整数,i,j,e,描述一个相等/不等的约束条件,若e=1,则该约束条件为xi=xj ,若e=0,则该约束条件为 xi≠xj 。
i,j,L≤100000
xi,xj≤
Output
输出共T行。
第一行一个整数T,表示数据组数。
接下来T行的第i行,一个整数,表示第i组数据中的约束条件个数。
第一行一个整数T,表示数据组数。
接下来T行的第i行,一个整数,表示第i组数据中的约束条件个数。
Sample Input
6
2 2 1
2 2 1
1 1 1
3 1 1
1 3 1
1 3 0
Sample Output
1
6
分析
本题一开始以为要用种类并查集做,但是本题和种类并查集不同的是,种类并查集应用的情况是固定的种类数,也就是非此即彼的情况,但是本题来说 1和2不同 2和3不同 未必代表1和3就相同
所以需要对于每一个根维护一个set 存储与其对立的根(注意是在根节点维护关于根的set,否则可能会出现遗漏)
对于a和b已经在同一个集的情况 ,如果约束条件为0 则代表到了本组最后一个条件,进行初始化
对于a和b不在同一个集的情况,如果约束条件为0 将彼此的根节点加入set中,如果约束条件为1 则遍历彼此根节点的set,如果不冲突就可以合并,注意合并的时候要把set一起合并,冲突的话说明到了本组最后一个条件,进行初始化
#include<bits/stdc++.h> using namespace std; int s[100005],anss[100005],num,sum,cnt,l,L,c,now,a[100005],b[100005]; set<int> st[100005]; int findf(int x) { return x==s[x]?x:s[x]=findf(s[x]); } void hebing(int fa,int fb) { s[fa]=fb; set<int>::iterator it; for(it=st[fa].begin();it!=st[fa].end();it++) //“敌人”也要一起合并 { st[fb].insert(*it); } for(it=st[fb].begin();it!=st[fb].end();it++) { st[fa].insert(*it); } } int pd(int fa,int fb) { if(st[fa].count(fb)||st[fb].count(fa)) //set中有冲突的根 { return 0; } else { return 1; } } void Init() { for(int i=0;i<now;i++) { s[a[i]]=a[i]; //初始化根节点 st[a[i]].clear(); //清空“敌人” s[b[i]]=b[i]; st[b[i]].clear(); } now=0; anss[cnt++]=num; num=0; } int main() { cin>>l; L=l; sum=0; cnt=0; now=0; for(int i=1;i<=L;i++) { s[i]=i; } while(l--) { cin>>a[now]>>b[now]>>c; num++; int fa=findf(a[now]); int fb=findf(b[now]); now++; if(fa==fb) //已经在同一个类 { if(c==0) //约束条件为不等 { sum++; Init(); } } else //现在还不在同一个类 { if(c==1) //约束条件为相等 进行判断 { if(pd(fa,fb)==1) //不冲突 可以合并 { hebing(fa,fb); } else { sum++; Init(); } } else //约束条件为不等,加入set { st[fa].insert(fb); //均以根为标记 st[fb].insert(fa); } } } cout<<sum<<endl; for(int i=0;i<cnt;i++) { cout<<anss[i]<<endl; } }