一、题面
二、分析
该题与之前做过的带权并查集的唯一区别就是数组开不下。所以需要用离散化的思想,只取那些有用的点来解决该问题。
离散化其实就是把这些所有用到的点收集后,去重,再排一下序,然后用新数组它们的下标代表他们。
接下来数组能开下了,就用带权并查集的做法去做,这里权值可以直接用bool值,然后随便写几个发现是异或关系。
但需要注意,这里还是需要将输入的坐标往左移一下,直接不去考虑同一个点的情况。
三、AC代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <iostream> 3 #include <fstream> 4 #include <cstring> 5 #include <algorithm> 6 using namespace std; 7 8 const int MAXN = 1e4+2; 9 int par[MAXN], A[MAXN], B[MAXN]; 10 int Temp[MAXN], Cnt; 11 bool Rank[MAXN], Odd[MAXN]; 12 13 void Init() 14 { 15 memset(par, -1, sizeof(par)); 16 memset(Rank, 0, sizeof(Rank)); 17 } 18 19 int Pos(int x) 20 { 21 int left = 0, right = Cnt-1, mid; 22 while(left <= right) 23 { 24 mid = (left+right)>>1; 25 if(Temp[mid] == x) 26 return mid; 27 else if(Temp[mid] > x) 28 right = mid-1; 29 else 30 left = mid+1; 31 } 32 return -1; 33 } 34 35 int Find(int x) 36 { 37 if(par[x] == -1) return x; 38 int t = Find(par[x]); 39 Rank[x] = Rank[x]^Rank[par[x]]; 40 return par[x] = t; 41 } 42 43 bool Union(int x, int y, bool flag) 44 { 45 int fx = Find(x); 46 int fy = Find(y); 47 if(fx == fy) 48 { 49 return (flag^Rank[y]) == Rank[x]; 50 } 51 else 52 { 53 par[fx] = fy; 54 Rank[fx] = flag^Rank[y]^Rank[x]; 55 return true; 56 } 57 } 58 59 int main() 60 { 61 //freopen("input.txt", "r", stdin); 62 int N, T, ans; 63 char op[5]; 64 while(scanf("%d", &N)!=EOF) 65 { 66 Cnt = 0; 67 Init(); 68 scanf("%d", &T); 69 for(int i = 0; i < T; i++) 70 { 71 scanf("%d %d %s", &A[i], &B[i], op); 72 A[i]--; //*** 73 Temp[Cnt++] = A[i]; 74 Temp[Cnt++] = B[i]; 75 Odd[i] = (op[0] == 'o'); 76 } 77 sort(Temp, Temp + Cnt); 78 Cnt = unique(Temp, Temp+Cnt) - Temp; 79 int x, y; 80 ans = T; 81 82 for(int i = 0; i < T; i++) 83 { 84 x = Pos(A[i]); 85 y = Pos(B[i]); 86 if(!Union(x, y, Odd[i])) 87 { 88 ans = i; 89 break; 90 } 91 } 92 printf("%d ", ans); 93 } 94 return 0; 95 }