• 【并查集】NOI2015 && 洛谷 P1955 程序自动分析


      这题?说实话,我觉得挺强的(毕竟我WA了8次,是我太cai)。

      开头放题目。


      首先,这是一道并查集的题目,不知道你看出来没有(反正我一开始想歪了)。

      既然知道是并查集,那就是一道小破题了啊。

      首先,很容易想到把所有e==1的操作放在前面,然后再进行e==0的操作。而在进行e==1的操作的时候,我们只要把它约束的两个变量放在同一个集合里面即可。在e==0,即存在一条不相等的约束条件,对于它约束的两个变量,如果在一个集合里面,那就不可能满足的啊。如不相等的约束条件都满足,那就YES。

      然而并没有那么简单。不然为什么会是 省选

      当我们看到数据范围->10的9次方.......(我哭了,你们呢?

      别告诉我你想开一个10的9次方的fa数组的话,MLE欢迎你。超限就凉凉啊(是我亲身经历,欢迎模仿)。

      所以这时候离散化就来了啊。


    离散化三部曲

    1. 去重。
    2. 排序。
    3. 二分。

      一个unique再加lower_bound,最后再sort一下,完事。()

       没学过的看这里(是我学离散化时看的博客)->https://www.cnblogs.com/cytus/p/8933597.html


    又到了放代码的时候啊........

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    const int MA=2e5+50;
    int n,tot;
    struct ss{
        int i,j,e;
    }ys[MA];
    int a[MA],fa[MA];
    bool flag;
    
    inline int read() {
        int res = 0; 
        bool bo = 0; 
        char c;
        while (((c = getchar()) < '0' || c > '9') && c != '-');
        if (c == '-') bo = 1; 
        else res = c - 48;
        while ((c = getchar()) >= '0' && c <= '9') res = (res << 3) + (res << 1) + (c - 48);
        return bo ? ~res + 1 : res;
    }
    
    int cmp(ss a,ss b) {
        if(a.e==b.e) return a.i<b.i;
        return a.e>b.e;
    }
    
    int fi(int x) {
        if(fa[x]==x) return x;
        return fa[x]=fi(fa[x]);
    } 
    
    void mem() {
        tot=0;
        memset(a,0,sizeof a);
        memset(ys,0,sizeof ys);
        memset(fa,0,sizeof fa);
        flag=0;
    }
    
    int main()
    {
        int t;
        t=read();
        while(t--) {
            mem();
            n=read();
            for(register int i=1;i<=n;i++) {
                ys[i].i=read();
                ys[i].j=read();
                ys[i].e=read();
                a[++tot]=ys[i].i;
                a[++tot]=ys[i].j;
            }
            sort(a+1,a+tot+1);
            int con=unique(a+1,a+tot+1)-a; 
            for(register int i=1;i<=n;i++) {
                ys[i].i=lower_bound(a+1,a+con+1,ys[i].i)-a;
                ys[i].j=lower_bound(a+1,a+con+1,ys[i].j)-a; 
            }
            for(register int i=1;i<=con;i++) fa[i]=i;
            sort(ys+1,ys+n+1,cmp);
            for(register int i=1;i<=n;i++) {
                int x=fi(ys[i].i);
                int y=fi(ys[i].j);
                if(ys[i].e) fa[x]=y;
                else if(x==y) {
                    printf("NO
    ");
                    flag=1;
                    break;
                }
            }
            if(!flag) printf("YES
    ");
        }
        return 0;
    }

    我的这个算法 ->2663ms.(据说超级慢,但是是正解

    然后呢这里还要介绍一下同组大佬的另一种方法(是不用离散化的........神犇方法QAQ).->300ms

    https://baka.online/noi2015%E7%A8%8B%E5%BA%8F%E8%87%AA%E5%8A%A8%E5%88%86%E6%9E%90/

    欢迎大家去看啊(毕竟我还是菜)。

    谢谢观看。

    ---OI是信仰,是真正应该被认真以待的东西.....!
  • 相关阅读:
    第07组 Beta冲刺(2/5)
    第07组 Beta冲刺(1/5)
    第07组 Alpha事后诸葛亮
    第07组 Alpha冲刺(6/6)
    【Beta】软件使用说明——致社长
    【Beta】“北航社团帮”发布声明——小程序v2.0与网页端v1.0
    【Beta】“北航社团帮”测试报告——小程序v2.0与网页端v1.0
    [技术博客] 小程序扫码登录网页端原理
    [技术博客] 用户验证码验证机制---redis缓存数据库的使用
    [技术博客] 如何避免在代码中多重render
  • 原文地址:https://www.cnblogs.com/qxyzili--24/p/10426009.html
Copyright © 2020-2023  润新知