日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2017百度之星初赛:A-1002. 数据分割(并查集+set)

發布時間:2024/1/1 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2017百度之星初赛:A-1002. 数据分割(并查集+set) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

數據分割

? ?Accepts: 102 ? ?Submissions: 1332 ?Time Limit: 2000/1000 MS (Java/Others) ? ?Memory Limit: 32768/32768 K (Java/Others) Problem Description

小w來到百度之星的賽場上,準備開始實現一個程序自動分析系統。

這個程序接受一些形如x_i = x_jx?i??=x?j???或?x_i \neq x_jx?i??x?j???的相等/不等約束條件作為輸入,判定是否可以通過給每個 w 賦適當的值,來滿足這些條件。

輸入包含多組數據。 然而粗心的小w不幸地把每組數據之間的分隔符刪掉了。 他只知道每組數據都是不可滿足的,且若把每組數據的最后一個約束條件去掉,則該組數據是可滿足的。

請幫助他恢復這些分隔符。

Input

11行:一個數字LL,表示后面輸入的總行數。

之后LL行,每行包含三個整數,i,j,ei,j,e,描述一個相等/不等的約束條件,若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,L100000

x_i , x_j \leq Lx?i??,x?j??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; }

總結

以上是生活随笔為你收集整理的2017百度之星初赛:A-1002. 数据分割(并查集+set)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。