【并查集】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是信仰,是真正应该被认真以待的东西.....!
原文地址:https://www.cnblogs.com/qxyzili--24/p/10426009.html