• CDOJ1927 爱吃瓜的伊卡洛斯(2) 【并查集】启发式合并+set


    伊卡洛斯很爱吃西瓜。一次,他来到一个西瓜摊旁,发现水果摊有N个西瓜,西瓜有红色、黄色、绿色、蓝色……等等数不清的颜色。 伊卡洛斯很想知道知道一些信息,便于老板交谈了起来。 当老板的话的第一个字符为”A”时,老板会告诉伊卡洛斯一些信息,格式如下: A x y 1 这句话表示第x个西瓜和第y个西瓜是同一种颜色的。 A x y 2这句话表示第x个西瓜和第y个西瓜是不同种颜色的。

    当然,为了考验伊卡洛斯有没有认真听, 老板也会时不时问伊卡洛斯一些问题,格式如下: Q x y 这句话表示询问第x个西瓜和第y个西瓜是不是同一种颜色,如果确定为同一种颜色,伊卡洛斯需要回答1;确定为不同种颜色,伊卡洛斯需要回答2;无法确定时伊卡洛斯回答3。 注意,伊卡洛斯是根据已获得的信息来回答的。也就是只有这个问题之前的信息才为已知信息。

    老板说,只有回答对他全部的问题,伊卡洛斯才能吃到瓜,他聪明的想到了让你来帮助他。

    Input

    第一行包含两个整数NMN是西瓜总数,M是以AQ开头的老板的话总和。
    以下M行,每行包含一条老板的话。形式有A x y 1A x y 2Q x y。 1N100000 1M200000 1X,YN 数据保证没有矛盾

    Output

    对于每一条Q指令,输出1/2/3代表两个西瓜颜色的关系。

    Hint

    西瓜的颜色可以有无数多种!

    思路:这题颜色有无穷多种,所以不能按照普通的并查集分块求对立。 
    可以用set存每一个集合的对立(不同颜色)集合,如果两个x,y颜色相同时,合并两个集合的对立集合。 
    合并的时候尽量将小的集合合并到大的集合中去。 

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cmath>
     5 #include <cstring>
     6 #include <set>
     7 using namespace std;
     8 
     9 const int N = 1e5+6;
    10 int f[N];
    11 set<int> s[N];
    12 
    13 int find(int x)
    14 {
    15     if(x==f[x])return x;
    16     else return f[x]=find(f[x]);
    17 }
    18 
    19 void unite(int x,int y)
    20 {
    21     x = find(x);
    22     y = find(y);
    23     if(x!=y)
    24     {
    25         if(s[x].size()>s[y].size())swap(x,y);
    26         // s[x] size is small
    27         f[x]=y;
    28         if(s[x].size())
    29         {
    30             set<int>:: iterator it;
    31             for(it = s[x].begin(); it != s[x].end(); it++)
    32                 s[y].insert(find(*it));
    33         }
    34     }
    35     return;
    36 }
    37 
    38 int main()
    39 {
    40     int n,m;
    41     char op[6];
    42     scanf("%d%d",&n,&m);
    43     for(int i=1;i<=n;i++)
    44         f[i]=i;
    45     while(m--)
    46     {
    47         scanf("%s",&op);
    48         int x,y,z;
    49         if(op[0] =='A')
    50         {
    51             scanf("%d%d%d",&x,&y,&z);
    52             if(z==1)
    53                 unite(x,y);
    54             else
    55             {
    56                 s[find(x)].insert(find(y));
    57                 s[find(y)].insert(find(x));
    58             }
    59         }
    60         else
    61         {
    62             scanf("%d%d",&x,&y);
    63             int xx = find(x);
    64             int yy = find(y);
    65             if(xx==yy)printf("1
    ");
    66             else if(s[xx].find(yy)!=s[xx].end() || s[yy].find(xx)!=s[yy].end())
    67                 printf("2
    ");
    68             else printf("3
    ");
    69         }
    70     }
    71     return 0;
    72 }
  • 相关阅读:
    vue项目根据不同环境动态配置接口
    微信内置浏览器手机按返回键,给出提示,是否要退出
    Mac更新系统后提示xcrun error
    curl请求本地域名问题
    PHP把PNG图片转化为JPG时透明背景变黑色
    安卓微信浏览器中window.location.href失效的问题
    上拉加载触底事件最简单写法
    记一次virtualbox和夜神模拟器冲突的问题
    技术总结
    input type file onchange上传文件的过程中,同一个文件二次上传无效的问题。
  • 原文地址:https://www.cnblogs.com/demian/p/9184820.html
Copyright © 2020-2023  润新知