一類並查集問題( POJ 1182 )

 
 
 
題意爲有三類動物,他們的食物鏈是環,即 A 吃 B, B 吃 C, C 吃 A。
給出一些動物的食物鏈關係,根據以前的關係,判斷當前關係是否正確。
因爲並查集是一棵森林,我們用一個數組 dist[i] 記錄並查集的樹中結點 i 與根的關係, 值爲 1 表示吃根結點, 2 表示被根結點吃,爲 0 表示兩者爲同一類動物。
對於輸入的關係 d x y :
1). 如果 x, y 屬於同一集合,判斷兩都關係是否合理,根據下圖:
 
x, y 爲同一集合, 所以 x, y 指向同一根。 x 與根 rt 的關係距離爲 dist[x],  y 與根 rt 的關係距離爲 dist[y],
根據輸入 x 與 y 的關係距離爲 d。 由圖有 d+ dist[y]== dist[x]  ( mod 3 )。
 
2). 如果 x, y 不屬於同一集合,根據下圖有:
 
圖中 x 與 rx 屬同一集合,rx 的 x 的根, y 與 ry 原同一集合,ry 爲 y 的根。 rx!= ry, x 與 y 不屬於同一集合,這時應當將 x, y 合併,這裏合併時將 rx 指向 ry,  ry 成了新集合的根,根據圖有:
d+ dist[y]== dist[x]+ dist[rx]  -->  dist[rx]= d+ dist[y]- dist[x]  求出了關係距離。
 
還有一個問題(就上圖而言): x 與 y 合併後, ry 成了新集合的根,這時原來以 rx 爲根的集合中的結點與 ry 的關係距離需要重新確定,如何確定:
假 設並查集樹爲 x->a->b->rx ->ry,  rx->ry 的關係距離已經求出,即 dist[rx] 已知, b 到 ry 的關係距離爲 b 到 rx 的距離加上 rx 到 ry 的距離和。 故 dist[b]= dist[b]+ dist[rx]。 依次求出。
 
代碼:

#include <stdio.h>
#include <stdlib.h>

int const N= 50010;
int n, k;
int uset[N], dist[N];

int find( int x ){
    if( x== uset[x] ) return x;
    int rt= find( uset[x] );
    dist[x]= ( dist[x]+ dist[ uset[x] ] )% 3;
    uset[x]= rt;
    return rt;
}

int main(){
    scanf("%d%d",&n,&k);
    for( int i= 0; i<= n; ++i ){
        uset[i]= i; dist[i]= 0; }
    int ans= 0;
    for( int i= 0; i< k; ++i ){
        int d, x, y;
        scanf("%d%d%d", &d, &x, &y ); d--;
            
        if( x> n || y> n ){ ans++; continue; }

        int rx= find(x), ry= find(y);
        if( rx== ry ){
            if( ( d+ dist[y] )% dist[x] ) ans++;
        }else{
            uset[rx]= ry;
            dist[rx]= ( d+ dist[y]- dist[x]+ 6 )% 3;
        }
    }
    printf("%d\n", ans );
    
    return 0;

轉自http://blogold.chinaunix.net/u3/113538/showart_2212684.html

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