题目链接: http://poj.org/problem?id=1733
题意: 输入n表示有一个长度为n的0,1字符串, m表示接下来有m行输入, 接下来的m行输入中x, y, even表示第x到第y个字符中间1的个数为偶数个, x, y, odd表示第x到第y个字符中间1的个数为奇数个, 若m句话中第k+1是第一次与前面的话矛盾, 输出k;
思路: 若x, y之间1的个数为偶数个, 那么1~x 与1~y中1的个数同奇偶性, 反之则异奇偶性, 我们可以将其理解为若输入x, y, even, 即x, y属于同种, 反之则属于不同种,
用种类并查集就可以啦...不过要注意三点, 一是数据范围1e9, 不能直接用做数组下标, 要先离散化一下; 二是输入的数据中x, y是闭区间, 不好处理, 我们可以将其化为半开区间来处理, (x-1, y] 或者 [x, y+1); 还有就是如果全部正确的话就输出m(这里wa了我好久~)....
代码:
1 #include <iostream>
2 #include <stdio.h>
3 #include <string.h>
4 #include <map>
5 #define MAXN 5010
6 using namespace std; 7
8 int rank[2*MAXN], pre[2*MAXN]; 9
10 int find(int x){ //***递归压缩路径
11 if(x!=pre[x]){ 12 int px=find(pre[x]); 13 rank[x]=rank[x]^rank[pre[x]]; //***更新rank[x]
14 pre[x]=px; 15 } 16 return pre[x]; 17 } 18
19 int jion(int x, int y, int d){ 20 int fx=find(x); 21 int fy=find(y); 22 if(fx==fy){ 23 if(rank[x]^rank[y]!=d){ 24 return 1; 25 }else{ 26 return 0; 27 } 28 }else{ 29 pre[fy]=fx; 30 rank[fy]=(rank[x]+rank[y]+d)%2; 31 } 32 return 0; 33 } 34
35 int main(void){ 36 map<int, int>mp; 37 int n, m, gg=0, jj=1; 38 mp.clear(); 39 scanf("%d%d", &n, &m); 40 for(int i=0; i<=2*MAXN; i++){ 41 pre[i]=i; 42 rank[i]=0; 43 } 44 for(int i=1; i<=m; i++){ 45 int x, y, d; 46 char ch[10]; 47 scanf("%d%d%s", &x, &y, ch); 48 if(!mp[x-1]){ 49 mp[x-1]=jj++; 50 } 51 if(!mp[y]){ 52 mp[y]=jj++; 53 } 54 if(strstr(ch, "even")){ 55 d=0; 56 }else{ 57 d=1; 58 } 59 if(jion(mp[x-1], mp[y], d)&&!gg){ 60 gg=i; 61 } 62 } 63 if(!gg){ 64 gg=m+1; 65 } 66 printf("%d\n", gg-1); 67 return 0; 68 }