poj1733(种类并查集+离散化)

题目链接: 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 }

 

posted @ 2016-12-03 20:48  geloutingyu  阅读(2133)  评论(0编辑  收藏  举报