zoukankan      html  css  js  c++  java
  • 种类并查集 + 离散化

    //http://acm.timus.ru/problem.aspx?space=1&num=1003
    //分析:树和递归最常用的思想是分治;并查集是一种合并树的数据结构;合并树或加入树节点时,我们只在意新建立的树边上相邻的两个树节点之间的关系,实际上树边只在意相邻两个树节点之间的关系
    //思路:可以讲一段连续区间的奇偶性表示成两个前缀和的奇偶性;将出现的离散的点用map离散化一下;将数量减少的点做一次种类并查集

     1 #include"iostream"
     2 #include"cstdio"
     3 #include"cstring"
     4 #include"map"
     5 using namespace std;
     6 const int N = 5010;
     7 int rt[N<<1],w[N<<1];   //带权(种类)并查集 begin,end
     8 map<int,int> mp;    //离散化,begin
     9 int tot;    //离散化,end
    10 int n,m,l,r;    //输入,begin
    11 char str[10];   //输入,end
    12 
    13 void paco(int a)
    14 {
    15     if(rt[a]==a) {  //分治终点
    16         return ;
    17     }
    18     paco(rt[a]);    //分治
    19     w[a] ^= w[rt[a]];   //回溯,begin 注:树根的w一定为0,我们只在意树边上的信息即可
    20     rt[a] = rt[rt[a]];     //回溯,end 注:我们只在意树边上的信息即可
    21 }
    22 
    23 bool unio(int a,int b,int cnd)  //路径压缩 + 条件判断(合法性判断+树的合并)
    24 {
    25     paco(a);
    26     paco(b);
    27     int rt_a = rt[a],rt_b = rt[b];
    28     if(rt_a==rt_b) {
    29         return w[a]^w[b]^(!cnd);    //搞个卡诺图化简一下
    30     }
    31     else {
    32         rt[rt_a] = rt_b;
    33         w[rt_a] = (w[a]+w[b]+cnd)&1;    //搞个状态转换图推一下,因为树根的w为0,所以两根之间的关系就是新树边的w值 注:我们只在意树边上的信息即可
    34     }
    35     return true;
    36 }
    37 
    38 int main()
    39 {
    40     int i,res;
    41     bool ok;
    42     while(scanf("%d",&n)!=EOF&&n!=-1) {
    43         scanf("%d",&m);
    44         for(i = 0; i<=m; ++i) {
    45             rt[i] = i;
    46         }
    47         memset(w,0,sizeof(int)*(m+1));
    48         mp.clear();
    49         tot = 1;
    50         res = 0;
    51         ok = 1;
    52         for(i = 1; i<=m; ++i) {
    53             scanf("%d%d%s",&l,&r,str);
    54             if(mp.find(l-1)==mp.end()) {    //离散化,begin
    55                 mp[l-1] = tot++;
    56             }
    57             if(mp.find(r)==mp.end()) {
    58                 mp[r] = tot++;
    59             }                               //离散化,end
    60             if(unio(mp[l-1],mp[r],str[0]=='o')) {
    61                 if(ok) {
    62                     ++res;
    63                 }
    64             }
    65             else {
    66                 ok = 0;
    67             }
    68         }
    69         printf("%d
    ",res);
    70     }
    71     return 0;
    72 }

    //拓展:map具有对数搜索,去除和插入操作的复杂度,可以用hash做离散化优化一下

  • 相关阅读:
    多个相同结构的表的字段的修改、添加
    SQL SERVER 查询去重 PARTITION BY
    message from server: "Host 'xxx' is not allowed to connect to th
    jdk 1.8 连接数据库
    恢复SQLServer数据库后,如何同步登陆名和用户名
    无法识别的属性“targetFramework”。请注意属性名称区分大小写。错误解决办法
    jquery.tablesorter 使用
    MD5加密
    C# 判断是否是节假日
    word ladder
  • 原文地址:https://www.cnblogs.com/AC-Phoenix/p/4264743.html
Copyright © 2011-2022 走看看