Mahmoud and a Dictionary CodeForces - 766D 种类并查集

题意

给出多个字符串 然后再输入多个字符串之间的关系 让我们判断这其中是否存在矛盾的关系 有矛盾输出NO 没矛盾输出 YES
然后再输入多个询问 每个询问 两个字符串 让我们判断其中的关系 同义词输出1 反义词输出2 不确定输出3

分析

种类并查集

如果两个字符串的关系 是1 表示同义
那么分情况讨论 如果两个词的根节点相同 那么表示有关系 那么如果与根节点的关系是相同的那么没错 如果与根节点的关系是不同的 那么有错
如果两个词的根节点不同 那么表示没关系 把他们的根节点连到一起
我们用0表示同义词 1表示反义词 当输入ab关系为1时
a 1 0 1 0
b 0 1 1 0 那么 对应的根节点关系可知
为0 0 1 1
当输入ab关系为0时
a 1 0 1 0
b 0 1 1 0 那么对应根节点关系
为1 1 0 0
当两个字符串输入关系为2时
那么如果两个字符根节点不同 那么就把他们连一起 新根节点关系可以有上面的统计结果分析得出
当两个字符串与根节点相同 那么如果他们与根的关系不同 那么没错 如果相同就有矛盾

code


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+7;
char a[22],b[22];
map<string,int>M;
int f[maxn],rel[maxn];
int find(int x){
    int t;
    if(x==f[x])return x;
    t = find(f[x]);
    rel[x] = (rel[f[x]]+rel[x]+1)%2;
    return f[x] = t;
}
int main()
{
    int n,m,q;
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=n;i++){
        scanf("%s",a);
        M[a]=i;
    }

    for(int i=1;i<=n;i++)f[i] = i,rel[i] = 1;

    while(m--){
        int F;
        scanf("%d%s%s",&F,a,b);
        int ta,tb,fa,fb;
        ta = M[a];
        tb = M[b];
        fa = find(ta);
        fb = find(tb);
        if(F==1){
            if(fa==fb){
                if(rel[ta]==rel[tb])puts("YES");
                else puts("NO");
            }
            else{
                f[fa] = fb;
                rel[fa] = (rel[ta]+rel[tb]+1)%2;
                puts("YES");
            }
        }
        else{
            if(fa==fb){
                if(rel[ta]==rel[tb])puts("NO");
                else puts("YES");
            }
            else{
                f[fa] = fb;
                rel[fa] = rel[ta]^rel[tb];
                puts("YES");
            }
        }
    }

    while(q--){
        scanf("%s%s",a,b);
        int ta  = M[a];
        int tb  = M[b];
        int fa = find(ta);
        int fb = find(tb);
        if(fa!=fb)puts("3");
        else if(rel[ta]==rel[tb])puts("1");
        else puts("2");
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值