首页 > 代码库 > 百度之星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