首页 > 代码库 > 百度之星2017 HDU 6109 数据分割 并查集+set
百度之星2017 HDU 6109 数据分割 并查集+set
数据分割
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6109
Description
小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
Output
输出共T+1行。
第一行一个整数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
题解
给定L行,要求划分成多组数据:除了最后一行外,任意一行都相互可满足,然而一旦加入最后一行则会与前面的描述产生矛盾。(比如令xi=xj, xj!=xk都是可满足的,一旦加上xi=xk则不可满足了)
题意
跟以前做过的一道“食物链”的题很像,相同之处就是通过判断一个集合是否可满足,以及涉及集合的合并,但是有区别:食物链中维持的关系具有传递性,但是本题中仅有相等关系满足传递性,不等关系是不满足传递性的,所以不能完全用并查集维护。
考虑这样:用set记录每个集合一定不相等的元素集合的集合,每次合并相同节点的时候将两个结点的set合并放到根节点处。每次对输入的相等关系,判断两个变量的根节点所维护的set是否含有对方的根节点,若没有则允许合并;对输入的不等关系,只需要判断两个元素是否在同一个集合中,若不在则将各自的根节点加入对方根节点的set中。
代码
1 //HDU-6109 copyright:scidylanpno 2 #include<bits/stdc++.h> 3 using namespace std; 4 const int MAXN = 100000+10; 5 set<int> SET[MAXN]; 6 int Set[MAXN]; 7 //Initialize 8 void makeSet(){ 9 for(int i=0;i<MAXN;i++) SET[i].clear(),Set[i]=-1; 10 } 11 //Find 12 int find(int x){ 13 if(Set[x]<0) return x; 14 int p=x,t; 15 while(Set[p]>=0){ 16 p=Set[p]; 17 } 18 while(x!=p){ 19 t=x; 20 x=Set[x]; 21 Set[t]=p; 22 } 23 return p; 24 } 25 //Union 26 void unionSet(int x,int y){ 27 int findX=find(x),findY=find(y); 28 if(findX==findY) return; 29 if(Set[findX]<Set[findY]){ 30 Set[findX]+=Set[findY]; 31 Set[findY]=findX; 32 SET[findX].insert(SET[findY].begin(),SET[findY].end()); 33 }else{ 34 Set[findY]+=Set[findX]; 35 Set[findX]=findY; 36 SET[findY].insert(SET[findX].begin(),SET[findX].end()); 37 } 38 } 39 int ans[MAXN]; 40 int main() 41 { 42 int L; 43 int cnt=0; 44 int T; 45 scanf("%d",&T); 46 int x,y,op; 47 int i=0; 48 makeSet(); 49 int findX,findY; 50 while(i<T) 51 { 52 scanf("%d%d%d",&x,&y,&op); 53 ans[cnt]++; 54 //cout<<ans[cnt]<<endl; 55 if(op==1) 56 { 57 findX=find(x),findY=find(y); 58 if(findX!=findY) 59 { 60 if(SET[findX].find(findY)!=SET[findX].end()||SET[findY].find(findX)!=SET[findY].end()) 61 { 62 makeSet(); 63 cnt++; 64 }else 65 { 66 unionSet(findX,findY); 67 } 68 } 69 }else 70 { 71 findX=find(x),findY=find(y); 72 if(findX==findY) makeSet(),cnt++; 73 else 74 { 75 SET[findX].insert(findY); 76 SET[findY].insert(findX); 77 } 78 } 79 i++; 80 } 81 //cnt++; 82 printf("%d\n",cnt); 83 for(int i=0;i<cnt;i++) 84 { 85 printf("%d\n",ans[i]); 86 } 87 return 0; 88 }
题解链接:http://www.cnblogs.com/scidylanpno/p/7354552.html
版权所有:scidylanpno
百度之星2017 HDU 6109 数据分割 并查集+set