51nod 1515 明辨是非 (并查集+启发式set合并)

给n组操作,每组操作形式为x y p。

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

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

Input输入一个数n表示操作的次数(n<=1*10^5) 
接下来n行每行三个数x,y,p(x,y<=1*10^8,p=0 or 1)Output对于n行操作,分别输出n行YES或者NOSample 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+5;
set<int> s[maxn];
set<int>::iterator it;
unordered_map<int,int> H;
int cnt=0,par[maxn];
int find(int x)
{
    if(x==par[x])
        return x;
    return par[x]=find(par[x]);
}
void uni_set(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(find(*it));
            s[find(*it)].erase(y);
            s[find(*it)].insert(x);
        }
        s[y].clear();
        par[y]=x;
    }
    else
    {
        for(it=s[x].begin();it!=s[x].end();it++)
        {
            s[y].insert(find(*it));
            s[find(*it)].erase(x);
            s[find(*it)].insert(y);
        }
        s[x].clear();
        par[x]=y;
    }
}
void uni(int x,int y)
{
    if(s[x].find(y)!=s[x].end())
    {
        cout<<"NO"<<endl;
        return ;
    }
    cout<<"YES"<<endl;
    uni_set(x,y);
}
int getid(int x)//坐标离散化
{
    if(H[x])
        return H[x];
    return H[x]=++cnt;
}
void spl(int x,int y)
{
    if(x==y)
    {
        cout<<"NO"<<endl;
        return ;
    }
    cout<<"YES"<<endl;
    s[x].insert(y);
    s[y].insert(x);
}
void init()
{
    for(int i=0;i<maxn;i++)
        par[i]=i;
}
int main()
{
    int n;
    cin>>n;
    init();
    for(int i=0;i<n;i++)
    {
        int x,y,p;
        cin>>x>>y>>p;
        x=find(getid(x));
        y=find(getid(y));
        if(p)
            uni(x,y);
        else
            spl(x,y);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/orion7/p/7274112.html