zoukankan      html  css  js  c++  java
  • poj1733 Parity game ****

      1 /*
    2 * poj-1733 Parity game.cpp
    3 *
    4 * Created on: 2012-2-17
    5 * Author: LongDou
    6 *
    7 *
    8 * hash离散化  + 并查集
    9 *
    10 * 设s[0]=0,s[i]=a[1]+a[2]+...+a[i],则信息i j even等价于a[i]+...+a[j]为偶数,即
    11 s[j]-s[i-1]为偶数,即s[j]与s[i-1]同奇偶。这样,每条信息都可以变为
    12 s[i-1]和s[j]是否同奇偶的信息。
    13
    14 若记:
    15 same[j]为当前和s[j]同奇偶的元素集合,
    16 diff[j]为和s[j]不同奇偶的元素集合,
    17 则一条信息i j even将导致same[j]和same[i-1]合并,diff[j]和diff[i-1]合并;
    18 信息i j odd将导致same[j]和diff[i-1]合并;diff[j]和same[i-1]合并。
    19
    20 另外无法直接开1000000000的数组,需离散化(用最简单的hash)
    21 *
    22 */
    23
    24 #include <cstdio>
    25 #include <cstring>
    26 using namespace std;
    27
    28 const int maxL = 10000 + 10;
    29 const int MOD = 9941; //hash
    30
    31 int len, qnum;
    32 //same[j]为s[j]的父节点,
    33 //diff[j]为与s[j]不同奇偶的某元素(即指向与s[j]不同奇偶的元素集合)
    34 int same[maxL], diff[maxL], rank[maxL];
    35 int hash[maxL];
    36
    37 void init(){
    38 for(int i=0; i<=maxL; i++){
    39 same[i] = i;
    40 diff[i] = -1;
    41 rank[i] = 0;
    42 hash[i] = -1;
    43 }
    44 }
    45
    46 int findSet(int x){
    47 if(x == -1) return -1;
    48 if(same[x] == x)
    49 return x;
    50
    51 int tmp = same[x];
    52 same[x] = findSet(tmp);
    53
    54 return same[x];
    55 }
    56
    57 void unionSet(int x, int y){
    58 if(x == -1 || y == -1) return;
    59
    60 int fx = findSet(x);
    61 int fy = findSet(y);
    62 if(fx == fy)
    63 return;
    64
    65 if(rank[fx] < rank[fy])
    66 same[fx] = fy;
    67 else if(rank[fy] < rank[fx])
    68 same[fy] = fx;
    69 else{
    70 same[fx] = fy;
    71 rank[fy]++;
    72 }
    73 }
    74
    75 int main(){
    76 scanf("%d%d", &len, &qnum);
    77
    78 init();
    79
    80 int a, b, sa, sb, da, db, ha, hb;
    81 char ans[5];
    82
    83 //
    84 for(int i=1; i<=qnum; i++){
    85 scanf("%d%d%s", &a , &b, ans);
    86 a--; //注意先减1
    87
    88 //离散化a
    89 ha = a % MOD;
    90 while(hash[ha] != -1 && hash[ha] != a)
    91 ha = (ha + 1) % MOD;
    92 hash[ha] = a;
    93 a = ha;
    94
    95 //离散化b
    96 hb = b % MOD;
    97 while(hash[hb] != -1 && hash[hb] != b)
    98 hb = (hb + 1) % MOD;
    99 hash[hb] = b;
    100 b = hb;
    101
    102 //各集合的代表元
    103 sa = findSet(a);
    104 da = findSet(diff[a]);
    105 sb = findSet(b);
    106 db = findSet(diff[b]);
    107
    108 if(!strcmp(ans, "even")){
    109 if(sa == db || da == sb){
    110 printf("%d\n", i-1);
    111 return 0;
    112 }
    113 if(diff[a] == -1) diff[a] = db; //设置diff[]
    114 if(diff[b] == -1) diff[b] = da;
    115 unionSet(sa, sb); //合并
    116 unionSet(da, db);
    117 }
    118 else if(!strcmp(ans, "odd")){
    119 if(sa == sb || (da != -1 && da == db)){
    120 printf("%d\n", i-1);
    121 return 0;
    122 }
    123 if(diff[a] == -1) diff[a] = sb; //设置diff[]
    124 if(diff[b] == -1) diff[b] = sa;
    125 unionSet(sa, db); //合并
    126 unionSet(da, sb);
    127 }
    128 }
    129 //全部正确,输出问题数
    130 printf("%d\n", qnum);
    131
    132
    133 return 0;
    134 }

      
      

      

    //再转一个其他方法实现的, 仍是并查集, 有点类似poj-1703 Find them, Catch them 的方法,离散化的方法与上面类似
      
    /*
    解题思路:hash离散化+并查集

      首先我们不考虑离散化:s[x]表示(root[x],x]区间1的个数的奇偶性,0-偶数,1-奇数

      每个输入区间[a,b],首先判断a-1与b的根节点是否相同

      a)如果相同表示(a-1,b]之间1的个数奇偶性已知s((a-1,b])=s[a-1]^s[b],此时只需简单判断即可

      b)如果不同,我们需要合并两个子树,我们将root较大的子树(例root[a])合并到root较小的子树(例root[b]),且此时s[root[a]]=s[a]^s[b]^s((a-1,b])

      在路径压缩的过程中s[i]=s[i]^s[root[i]],s[root[i]]为(root[root[i]], root[i]]区间内1个数的奇偶性,例(a, b]区间1的个数为偶数,(b, c]区间1的个数为奇数,(a, c]之间1的个数显然为0^1=1奇数
    */

    #include <iostream>
    using namespace std;
    #define MOD 9941
    #define MAX 10005

    struct node
    {
    node():next(0){}
    int val, index;
    node* next;
    }HashMap[MOD];

    int root[MAX],num[MAX],u=0;
    char c[MAX];

    //hash离散化,找到x对应的离散化后的值
    int find(int x)
    {
    int y = x%MOD;
    node *p,*q;
    p = &HashMap[y], q = HashMap[y].next;
    while (q)
    if(q->val == x)return q->index;
    else p=q,q=q->next;
    node *temp=new node(); temp->val=x,temp->index=++u,p->next=temp,num[u]=x;
    return u;
    }

    //并查集-x的根结点
    int findroot(int x)
    {
    int t;
    if(root[x]!=x){t = root[x];root[x]=findroot(root[x]);c[x] = c[t]^c[x];}
    return root[x];
    }


    int main()
    {
    int i,l,n,s,t,r1,r2,v,ans;
    bool IsError = false;
    char ch[5];
    for(i=0;i<MAX;i++)root[i]=i,c[i]=0;
    scanf("%d\n%d", &l, &n);

    for (i=1; i<=n;i++)
    {
    scanf("%d %d %s", &s, &t, ch);
    if(IsError)continue;
    v = (ch[0] == 'e')?0:1;

    s=find(s-1),t=find(t); //离散化后的值
    r1=findroot(s), r2=findroot(t); //根结点
    if(r1==r2 && (c[s]^c[t]^v)){IsError=true;ans=i-1;}
    else if(r1 != r2)
    {
    if(num[r1]<num[r2])root[r2]=r1,c[r2]=c[s]^c[t]^v;
    else root[r1]=r2, c[r1]=c[s]^c[t]^v;
    }
    }
    IsError ? printf("%d\n",ans) : printf("%d\n", n);

    return 0;
    }


  • 相关阅读:
    lombok 下的@Builder注解用法
    吉特日化MES实施--三种浪费
    吉特日化MES配料工艺参数标准版-第二版
    吉特日化MES系统&生产工艺控制参数对照表
    吉特日化MES & SQL Server 无法执行数据库脚本
    吉特日化MES系统--通过浏览器调用标签打印
    吉特日化MES&WMS系统--三色灯控制协议转http
    吉特仓储管理系统-库存管理分类汇总
    “千言数据集:文本相似度”权威评测,网易易智荣登榜首
    网易有数品牌升级:聚焦数据价值,助力企业数字化创新
  • 原文地址:https://www.cnblogs.com/longdouhzt/p/2356120.html
Copyright © 2011-2022 走看看