51nod 1515 明辨是非 启发式合并

1515 明辨是非

题目连接:

https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1515

Description

给n组操作,每组操作形式为x y p。
当p为1时,如果第x变量和第y个变量可以相等,则输出YES,并限制他们相等;否则输出NO,并忽略此次操作。
当p为0时,如果第x变量和第y个变量可以不相等,则输出YES,并限制他们不相等 ;否则输出NO,并忽略此次操作。

Input

输入一个数n表示操作的次数(n<=110^5)
接下来n行每行三个数x,y,p(x,y<=1
10^8,p=0 or 1)

Output

对于n行操作,分别输出n行YES或者NO

Sample Input

3
1 2 1
1 3 1
2 3 0

Sample Output

YES
YES
NO

题意

题解:

相同的,就直接并查集去维护就好了

不相同的,就set启发式合并去莽一波就好了

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+7;
int n,m,cnt,x,y,op,fa[maxn];
unordered_map<int,int> H;
set<int>s[maxn];
set<int>::iterator it;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int fi(int x)
{
    if(x==fa[x])return x;
    fa[x]=fi(fa[x]);return fa[x];
}
void set_uni(int x,int y)
{
    if(x==y)return;
    if(s[x].size()>s[y].size())
    {
        for(it=s[y].begin();it!=s[y].end();it++)
        {
            s[x].insert(fi(*it));
            s[fi(*it)].erase(y);
            s[fi(*it)].insert(x);
        }
        s[y].clear();
        fa[y]=x;
    }
    else
    {
        for(it=s[x].begin();it!=s[x].end();it++)
        {
            s[y].insert(fi(*it));
            s[fi(*it)].erase(x);
            s[fi(*it)].insert(y);
        }
        s[x].clear();
        fa[x]=y;
    }
}
int getid(int x)
{
    if(H[x]==0)H[x]=++cnt;
    return H[x];
}
void uni(int x,int y)
{
    if(s[x].find(y)!=s[x].end()){printf("NO\n");return;}
    printf("YES\n");
    set_uni(x,y);
}
void spl(int x,int y)
{
    if(x==y){printf("NO\n");return;}
    printf("YES\n");
    s[x].insert(y);
    s[y].insert(x);
}
int main()
{
    int n;scanf("%d",&n);
    for(int i=0;i<maxn;i++)fa[i]=i;
    for(int i=1;i<=n;i++)
    {
        x=read(),y=read(),op=read();
        x=fi(getid(x)),y=fi(getid(y));
        if(op==1)uni(x,y);
        else spl(x,y);
    }
}

你可能感兴趣的:(51nod 1515 明辨是非 启发式合并)