UVa10158 War(並查集)
阿新 • • 發佈:2019-01-03
這道題是並查集的應用,很好的題型
思路我也是參照別人的思路,不過思路很簡單的
題中說了很多很複雜的關於朋友還是敵人的東西,其實你讀透了就會發現,其實就是一句話,如果你是我的朋友的朋友,那麼我們就有公共的敵人
也就是說這個朋友圈的人, 和敵人圈的人沒有交集;
但是到底是朋友還是敵人,怎麼表示
n個人,用2*n個點表示,前n個表示本身,後n個表示相應點的分身,如果是朋友,就把本身加進去,如果是敵人,就把分身加進去
判斷是不是敵人的時候,就看相應的分身和另一個本身是不是在一個集合裡;如果判斷是不是朋友,就看兩個本身在不在一個集合裡面
程式碼如下:
#include <cstdio> #include <cstring> const int N = 20020; int fa[N], n; int find ( int a ) { return fa[a] == a ? a : fa[a] = find(fa[a]); } void setFriend( int a, int b ) { int x1, x2, y1, y2; x1 = find(a), y1 = find(b); x2 = find(a+n), y2 = find(b+n); if ( x1 == y2 || x2 == y1 ) printf("-1\n"); else { fa[x1] = y1; fa[x2] = y2; } } void setEnemy( int a, int b ) { int x1, x2, y1, y2; x1 = find(a), y1 = find(b); x2 = find(a+n), y2 = find(b+n); if ( x1 == y1 ) printf("-1\n"); else { fa[x1] = y2; fa[y1] = x2; } } void areFriend( int a, int b ) { int x, y; x = find(a); y = find(b); if ( x == y ) printf("1\n"); else printf("0\n"); } void areEnemy( int a, int b ) { int x1, x2, y1, y2; x1 = find(a), y1 = find(b); x2 = find(a+n), y2 = find(b+n); if ( x2 == y1 || x1 == y2 ) printf("1\n"); else printf("0\n"); } int main() { while ( scanf("%d", &n) != EOF ) { int c, a, b; for ( int i = 0; i <= n*2; ++i ) fa[i] = i; while ( 1 ) { scanf("%d%d%d", &c, &a, &b); if ( a == 0 && c == 0 && b == 0 ) break; if ( c == 1 ) setFriend( a, b ); else if ( c == 2 ) setEnemy( a, b ); else if ( c == 3 ) areFriend( a, b ); else if ( c == 4 ) areEnemy( a, b ); } } return 0; }