题解 CF766D 【Mahmoud and a Dictionary】

CF766D

算法: 带权并查集

看到许多大佬都用的扩展域,不会,是黑题,有点激动,因为终于有一道黑题了QwQ

进入正题


题意: 有一些单词,每次给出两个单词的关系(近义词或反义词),输出与前面的关系是否矛盾,在有一些询问,询问两个单词的关系,近义词的近义词是近义词,近义词的反义词是反义词,反义词的反义词是近义词,虽然这不合理

乍一看,觉得应该没有权值,仔细思考才发现近义词或反义词本质上就是到根的异或和。

类似于转移方程的东东(关键步骤):sum[x]^=sum[pa[x]];

可以用map来把单词映射到数组上,这样会方便的多

code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,q,pa[100001],sum[100001],tp,x,y;
string s,s1,s2;
map<string,int> mp;
int root(int x)
{
    if (pa[x]==x) return x;
    int rt=root(pa[x]);
    sum[x]^=sum[pa[x]];
    pa[x]=rt;
    return rt;
}
signed main()
{
    cin>>n>>m>>q;
    for (int i=1;i<=n;i++)
    {
        cin>>s;
        mp[s]=i;
    }
    for (int i=1;i<=n;i++) pa[i]=i;
    for (int i=1;i<=m;i++)
    {
        cin>>tp>>s1>>s2;
        x=mp[s1];y=mp[s2];
        if (tp==1)
        {
            int rx=root(x),ry=root(y);
            if (rx==ry)
            {
                if (sum[x]!=sum[y]) printf("NO\n");
                else printf("YES\n");
            }
            else
            {
                printf("YES\n");
                pa[rx]=ry;
                sum[rx]=sum[x]^sum[y];
            }
        }
        else
        {
            int rx=root(x),ry=root(y);
            if (rx==ry)
            {
                if (sum[x]==sum[y]) printf("NO\n");
                else printf("YES\n");
            }
            else
            {
                printf("YES\n");
                pa[rx]=ry;
                sum[rx]=sum[x]^sum[y]^1;
            }
        }
    }
    for (int i=1;i<=q;i++)
    {
        cin>>s1>>s2;
        x=mp[s1];y=mp[s2];
        int rx=root(x),ry=root(y);
        if (rx!=ry) printf("3\n");
        else 
        {
            if (sum[x]==sum[y]) printf("1\n");
            else printf("2\n");
        }
    }
    return 0;
}

不!准!抄! 除非你真的看懂了

posted @ 2020-10-10 12:16  寂静的海底  阅读(2)  评论(0编辑  收藏  举报  来源