2017百度之星初赛:A-1002. 数据分割(并查集+set)
數(shù)據(jù)分割
? ?Accepts: 102 ? ?Submissions: 1332 ?Time Limit: 2000/1000 MS (Java/Others) ? ?Memory Limit: 32768/32768 K (Java/Others) Problem Description小w來到百度之星的賽場上,準(zhǔn)備開始實(shí)現(xiàn)一個(gè)程序自動(dòng)分析系統(tǒng)。
這個(gè)程序接受一些形如x_i = x_jx?i??=x?j???或?x_i \neq x_jx?i??≠x?j???的相等/不等約束條件作為輸入,判定是否可以通過給每個(gè) w 賦適當(dāng)?shù)闹?#xff0c;來滿足這些條件。
輸入包含多組數(shù)據(jù)。 然而粗心的小w不幸地把每組數(shù)據(jù)之間的分隔符刪掉了。 他只知道每組數(shù)據(jù)都是不可滿足的,且若把每組數(shù)據(jù)的最后一個(gè)約束條件去掉,則該組數(shù)據(jù)是可滿足的。
請(qǐng)幫助他恢復(fù)這些分隔符。
Input第11行:一個(gè)數(shù)字LL,表示后面輸入的總行數(shù)。
之后LL行,每行包含三個(gè)整數(shù),i,j,ei,j,e,描述一個(gè)相等/不等的約束條件,若e=1e=1,則該約束條件為x_i = x_jx?i??=x?j???,若e=0e=0,則該約束條件為?x_i \neq x_jx?i??≠x?j???。
i,j,L \leq 100000i,j,L≤100000
x_i , x_j \leq Lx?i??,x?j??≤L
Output輸出共T+1T+1行。
第一行一個(gè)整數(shù)TT,表示數(shù)據(jù)組數(shù)。
接下來TT行的第ii行,一個(gè)整數(shù),表示第i組數(shù)據(jù)中的約束條件個(gè)數(shù)。
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
既然題目說每組數(shù)據(jù)把最后一個(gè)約束條件去掉就合理
那么只要將這L組約數(shù)條件從前往后遍歷一下就好了
初始化一個(gè)空集,將約束條件一個(gè)一個(gè)加入集合里,當(dāng)加到某個(gè)約束條件之后不合理了,
就說明這是最后一個(gè)約束條件,把它刪掉,之后集合里剩下的約束條件個(gè)數(shù)就是當(dāng)前答案
然后清空集合,繼續(xù)
主要是如何判斷它突然就不合理了
很顯然相等是有傳遞性的,也就是說這個(gè)并查集就能輕松搞定
但是不相等不具有傳遞性
那么考慮暴力,開100000個(gè)set,set[x]里面存的是所有與x不相等的數(shù)
那么有題解:
每個(gè)約束x≠y,只要看x和y是否在同一個(gè)并查集里就好,如果在同一并查集說明不合理
否則合理,set[x].insert(y), set[y].insert(x)
每個(gè)約束x==y,看set[x]里是否有y,set[y]里是否有x,如果有則不合理,否則將x和y加入并查集
但是這樣是錯(cuò)的,上面紫色的部分錯(cuò)了!
因?yàn)橛羞@種情況:x和y相等,x和z不相等,那么y和z肯定也不相等
也就是說只要z和x不相等,那么和x在同一個(gè)并查集合里的所有數(shù)都和z不相等
這個(gè)時(shí)候要將x并查集里所有的數(shù)都insert(z),肯定超時(shí)
所以只能將所有的并查集歸為一類,set[x]里面存的是所有與x并查集里面的數(shù)不相等的數(shù)
然后并查集合并的時(shí)候set跟著一起合并
因?yàn)樽疃嘀粫?huì)有L對(duì)約束關(guān)系,出現(xiàn)最多2L個(gè)數(shù),而并查集是O(n)的
所以處理的好的話復(fù)雜度是基本上線性的,只有額外set的復(fù)雜度
不要輕易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; }
總結(jié)
以上是生活随笔為你收集整理的2017百度之星初赛:A-1002. 数据分割(并查集+set)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个程序教你花式示爱 1——波动心形线
- 下一篇: 华为荣耀+T8950