这道题是并查集的应用,很好的题型
思路我也是参照别人的思路,不过思路很简单的
题中说了很多很复杂的关于朋友还是敌人的东西,其实你读透了就会发现,其实就是一句话,如果你是我的朋友的朋友,那么我们就有公共的敌人
也就是说这个朋友圈的人, 和敌人圈的人没有交集;
但是到底是朋友还是敌人,怎么表示
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; }