HDU6109 數據分割【並查集】

數據分割

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2449 Accepted Submission(s): 742

Problem 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

Source
2017"百度之星"程序設計大賽 - 初賽(A)

問題鏈接HDU6109 數據分割
問題簡述:題目比較繞,不敢恭維啊!給定n個表達式,表示a==b或者a!=b,有矛盾就刪除掉重新開始,計算這些表達式可以分成多少段,每段多大。
問題分析:想等具有可傳遞性,想等的元素(表達式兩邊的變量)存儲在同一集合set中,用數組ans來存儲階段性結果。其他內容看代碼,不解釋。
程序說明:(略)
參考鏈接:(略)
題記:(略)

AC的C++語言程序如下:

/* HDU6109 數據分割 */

#include <bits/stdc++.h>

using namespace std;

const int N = 100000;
set<int> s[N + 1];
int f[N + 1];
void UFInit(int n) {for(int i = 0; i <= n; i++) f[i] = i, s[i].clear();}
int Find(int a) {return a == f[a] ? a : f[a] = Find(f[a]);}
void Union(int a, int b) {if ((a = Find(a)) != (b = Find(b))) f[a] = b;}

int cnt = 0, ans[N + 1];

int main()
{
    int l, i, j, e;

    UFInit(N);
    memset(ans, 0, sizeof(ans));
    scanf("%d", &l);
    for(int k = 1; k <= l; k++) {
        scanf("%d%d%d", &i, &j, &e);
        int u = Find(i);
        int v = Find(j);
        if(e) {
            if(u == v) continue;
            else if(s[u].find(v) != s[u].end()) {
                ans[++cnt] = k;
                UFInit(N);
            } else {
                for(set<int>::iterator iter = s[v].begin(); iter != s[v].end(); iter++) {
                    s[u].insert(*iter);
                    s[*iter].erase(v);
                    s[*iter].insert(u);
                }
                s[v].clear();
                f[v] = u;
            }
        } else {
            if(u == v) {
                ans[++cnt] = k;
                UFInit(N);
            } else {
                s[u].insert(v);
                s[v].insert(u);
            }
        }
    }

    printf("%d\n", cnt);
    for(int i = 1; i <= cnt; i++)
        printf("%d\n", ans[i] - ans[i - 1]);

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章