2017百度之星初赛:A-1002. 数据分割(并查集+set)
2017-08-12 18:58
169 查看
数据分割
Accepts: 102
Submissions: 1332
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
小w来到百度之星的赛场上,准备开始实现一个程序自动分析系统。
这个程序接受一些形如x_i
= x_jxi=xj 或 x_i
\neq x_jxi≠xj 的相等/不等约束条件作为输入,判定是否可以通过给每个
w 赋适当的值,来满足这些条件。
输入包含多组数据。 然而粗心的小w不幸地把每组数据之间的分隔符删掉了。 他只知道每组数据都是不可满足的,且若把每组数据的最后一个约束条件去掉,则该组数据是可满足的。
请帮助他恢复这些分隔符。
Input
第11行:一个数字LL,表示后面输入的总行数。
之后LL行,每行包含三个整数,i,j,ei,j,e,描述一个相等/不等的约束条件,若e=1e=1,则该约束条件为x_i
= x_jxi=xj ,若e=0e=0,则该约束条件为 x_i
\neq x_jxi≠xj 。
i,j,L
\leq 100000i,j,L≤100000
x_i
, x_j \leq Lxi,xj≤L
Output
输出共T+1T+1行。
第一行一个整数TT,表示数据组数。
接下来TT行的第ii行,一个整数,表示第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组约数条件从前往后遍历一下就好了
初始化一个空集,将约束条件一个一个加入集合里,当加到某个约束条件之后不合理了,
就说明这是最后一个约束条件,把它删掉,之后集合里剩下的约束条件个数就是当前答案
然后清空集合,继续
主要是如何判断它突然就不合理了
很显然相等是有传递性的,也就是说这个并查集就能轻松搞定
但是不相等不具有传递性
那么考虑暴力,开100000个set,set[x]里面存的是所有与x不相等的数
那么有题解:
每个约束x≠y,只要看x和y是否在同一个并查集里就好,如果在同一并查集说明不合理
否则合理,set[x].insert(y), set[y].insert(x)
每个约束x==y,看set[x]里是否有y,set[y]里是否有x,如果有则不合理,否则将x和y加入并查集
但是这样是错的,上面紫色的部分错了!
因为有这种情况:x和y相等,x和z不相等,那么y和z肯定也不相等
也就是说只要z和x不相等,那么和x在同一个并查集合里的所有数都和z不相等
这个时候要将x并查集里所有的数都insert(z),肯定超时
所以只能将所有的并查集归为一类,set[x]里面存的是所有与x并查集里面的数不相等的数
然后并查集合并的时候set跟着一起合并
因为最多只会有L对约束关系,出现最多2L个数,而并查集是O(n)的
所以处理的好的话复杂度是基本上线性的,只有额外set的复杂度
不要轻易memset
#include<stdio.h> #include<set> #include<string.h> #include<algorithm> using namespace std; set<int> un[100005], st; int cnt, ufs[100005], ans[100005]; int Find(int x) { if(ufs[x]==-1) return x; return ufs[x] = Find(ufs[x]); } void Union(int x, int y) { set<int>::iterator it; if(x==y) return; if(un[x].size()>un[y].size()) swap(x, y); for(it=un[x].begin();it!=un[x].end();it++) { un[*it].erase(x); un[*it].insert(y); un[y].insert(*it); } ufs[x] = y; } int main(void) { int L, i, x, y, t, t1, t2, sum; set<int>::iterator it; scanf("%d", &L); memset(ufs, -1, sizeof(ufs)); sum = 0; while(L--) { sum++; scanf("%d%d%d", &x, &y, &t); st.insert(x); st.insert(y); t1 = Find(x), t2 = Find(y); if(t==1) { if(t1==t2 || un[t1].count(t2)==0) Union(t1, t2); else { ans[++cnt] = sum; sum = 0; for(it=st.begin();it!=st.end();it++) { un[*it].clear(); ufs[*it] = -1; } st.clear(); } } else { if(t1==t2) { ans[++cnt] = sum; sum = 0; for(it=st.begin();it!=st.end();it++) { un[*it].clear(); ufs[*it] = -1; } st.clear(); } else { un[t1].insert(t2); un[t2].insert(t1); } } } printf("%d\n", cnt); for(i=1;i<=cnt;i++) printf("%d\n", ans[i]); return 0; }
相关文章推荐
- 【百度之星初赛A】1002 数据分割(并查集+Set)
- 【2017"百度之星"程序设计大赛 - 初赛(A)】数据分割
- HDU 6109 数据分割 【并查集+set】 (2017"百度之星"程序设计大赛 - 初赛(A))
- 2017百度之星初赛B-1002(HDU-6115)
- HDU 6109 数据分割 【并查集+set】 (2017"百度之星"程序设计大赛 - 初赛(A))
- 2017百度之星初赛B-1002(HDU-6115)
- 2017百度之星初赛(B) 1002 Factory(倍增法求LCA)
- 2017"百度之星"程序设计大赛 - 初赛(A)数据分割
- HDU 6109 百度之星2017 1002 数据分割(并查集+set)
- 百度之星初赛(A)--数据分割----启发式合并
- 百度之星 数据分割 并查集+set
- 2017"百度之星"程序设计大赛 - 初赛(A) [ hdu 6108 小C的倍数问题 ] [ hdu 6109 数据分割 ] [ hdu 6110 路径交 ] [ hdu 6112 今夕何夕 ] [ hdu 6113 度度熊的01世界 ]
- 百度之星 2017初赛第一场 1001 小C的倍数问题
- 2017百度之星初赛:A-1001. 小C的倍数问题
- HDU 6108 小C的倍数问题 (数论 2017百度之星初赛A第1题)
- 百度之星2017初赛A-1005-今夕何夕
- (最小费用流)hdu 6118(2017百度之星初赛B 1005) 度度熊的交易计划
- 2017百度之星初赛2 小小粉丝度度熊
- 2017百度之星初赛(A)1001 小C的倍数问题(求因子数)
- 2017百度之星初赛:A-1005. 今夕何夕