题目链接:UVa10158 War(并查集)
这道题看着不难,也很明显是用并查集做,但是我自己写的代码一直是Runtime error,现在还是不知道为什么。网上找了一个题解,看了好长时间也没看懂。两份代码先都放这里吧,以后回头再看没准会懂。希望这样。
我自己写的代码:
#include <iostream> #include <vector> #include <algorithm> using namespace std; const int MAX_N = 10000 + 1000; vector <int> enemies[MAX_N]; int p[MAX_N]; int u,v,x,y,c,N; int setEnemies(int x,int y); int setFriends(int x,int y); bool areFriends(int x,int y); bool areEnemies(int x,int y); int Find(int x); void Union(int u,int v); int Find(int x) { return p[x] == x ? x : (p[x] = Find(p[x])); } void Union(int u,int v) { p[u] = v; } bool areFriends(int x,int y) { u = Find(x); v = Find(y); if(u == v) return true;//已经是朋友 return false; } bool areEnemies(int x,int y) { vector<int>::iterator result = find(enemies[x].begin(),enemies[x].end(),y); if(result != enemies[x].end()) return true; return false; } int setFriends(int x,int y) { if(areEnemies(x,y)) return -1; if(areFriends(x,y)) return 1; u = Find(x); v = Find(y); if(u != v) Union(u,v); vector<int>:: iterator i; for(i = enemies[x].begin();i != enemies[x].end();i++) { if(!areEnemies(y,*i)) setEnemies(y,*i); } for(i = enemies[y].begin();i != enemies[y].end();i++) { if(!areEnemies(x,*i)) setEnemies(x,*i); } return 1; } int setEnemies(int x,int y) { if(areFriends(x,y)) return -1; if(areEnemies(y,x)) return 1; vector<int>:: iterator i; for(i = enemies[x].begin();i != enemies[x].end();i++) setFriends(y,*i); for(i = enemies[y].begin();i != enemies[y].end();i++) setFriends(x,*i); int j; int x_f = Find(x);// x的朋友圈代表 int y_f = Find(y);// y的朋友圈代表 for(j = 0;j < N;j++) { if(x_f == Find(j) && j != x) { if(!areEnemies(j,y)) { enemies[j].push_back(y); enemies[y].push_back(j); } } if(y_f == Find(j) && j != y) { if(!areEnemies(j,x)) { enemies[j].push_back(x); enemies[x].push_back(j); } } } enemies[x].push_back(y); enemies[y].push_back(x); } int main() { cin>>N; int i; for(i = 0;i < N;i++) p[i] = i;//编号从零开始 while(cin>>c>>x>>y ,c || x || y) { switch(c) { case 1: if(setFriends(x,y) == -1) cout<<-1<<endl; break; case 2: if(setEnemies(x,y) == -1) cout<<-1<<endl; break; case 3: if(areFriends(x,y)) cout<<1<<endl; else cout<<0<<endl; break; case 4: if(areEnemies(x,y)) cout<<1<<endl; else cout<<0<<endl; break; } } return 0; }
#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; }