题解 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;
}
不!准!抄! 除非你真的看懂了
本文已经结束了。本文作者:ღꦿ࿐(DeepSea),转载请注明原文链接:https://www.cnblogs.com/Dreamerkk/p/17971020,谢谢你的阅读或转载!