1. 程式人生 > >poj1703 Find them, Catch them(帶權並查集)

poj1703 Find them, Catch them(帶權並查集)

har find 輸出 scanf -- oot n) puts stdin

題目鏈接

http://poj.org/problem?id=1703

題意

有兩個幫派:龍幫和蛇幫,兩個幫派共有n個人(編號1~n),輸入m組數據,每組數據為D [a][b]或A [a][b],D[a][b]表示a,b屬於不同的幫派,A [a][b]則讓我們判斷a,b是否屬於一個幫派,根據判斷的結果進行相應的輸出。

思路

這題和poj2492很像,使用並查集解決,方法我已在poj2492的題解中寫出,這裏不再贅述。

代碼

 1 #include <cstdio>
 2 using namespace std;
 3 
 4 const int N = 100000 + 10;
5 int p[N]; 6 int r[N]; 7 8 void make_set(int n) 9 { 10 for (int i = 1;i <= n;i++) 11 { 12 p[i] = -1; 13 r[i] = 0; 14 } 15 } 16 17 int find_root(int x) 18 { 19 if (p[x] == -1) 20 return x; 21 22 int t = p[x]; 23 p[x] = find_root(p[x]);
24 r[x] = (r[x] + r[t]) % 2; 25 return p[x]; 26 } 27 28 void union_set(int a, int b) 29 { 30 int ra = find_root(a); 31 int rb = find_root(b); 32 33 if (ra != rb) 34 { 35 p[ra] = rb; 36 r[ra] = (r[a] + r[b] + 1) % 2; 37 } 38 } 39 40 int main()
41 { 42 //freopen("poj1703.txt", "r", stdin); 43 int t; 44 scanf("%d", &t); 45 while (t--) 46 { 47 int n, m; 48 scanf("%d%d", &n, &m); 49 make_set(n); 50 char c; 51 int a, b; 52 for (int i = 0;i < m;i++) 53 { 54 getchar(); 55 scanf("%c%d%d", &c, &a, &b); 56 if (c == A) 57 { 58 if (find_root(a) == find_root(b)) //a,b在一個集合裏 59 { 60 if (r[a] == r[b]) //a,b為同一幫派 61 puts("In the same gang."); 62 else puts("In different gangs."); //a,b為不同幫派 63 } 64 else puts("Not sure yet."); //a,b不再同一集合裏,故不確定 65 } 66 else union_set(a, b); 67 } 68 } 69 return 0; 70 }

註意點

1、函數union_set要寫成這樣:

//正確寫法
void union_set(int a, int b)
{
    int ra = find_root(a);
    int rb = find_root(b);

    if (ra != rb)
    {
        p[ra] = rb;
        r[ra] = (r[a] + r[b] + 1) % 2;
    }
}

寫成如下形式會MLE:

//錯誤寫法,MLE
void union_set(int a, int b)
{
    int ra = find_root(a);
    int rb = find_root(b);

    p[ra] = rb;
    r[ra] = (r[a] + r[b] + 1) % 2;
}

2、使用scanf輸入。

相似題目

1、poj2492

poj1703 Find them, Catch them(帶權並查集)