CF 766D 带权并查集
题目大意:
给你N个单词M段关系还有Q个询问,关系包括喜欢和不喜欢;对于输入的每段关系,输出“YES”代表不矛盾,“NO”代表矛盾,若这两个单词没有关系则按输入的关系为它们建立关系并输出YES;对于每个询问,如果这两个单词没关系输出3 同义词输出1 反义词输出2 **【带权并查集裸题】******欢迎大佬多多指教!
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<string>
using namespace std;
int n,m,q;
typedef long long LL;
const int N=1e5+10;
int fa[N];
int R[N]; //设定同义词R[i]=0 反义词R[i]=1
char a[30],b[30];
map<string,int>M;
int fi(int x) //路径压缩
{
if(x!=fa[x])
{
int t=fa[x];
fa[x]=fi(fa[x]);
R[x]=(R[t]+R[x])%2;
}
return fa[x];
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&q))
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
R[i]=0;
}
int op;
for(int i=0;i<n;i++)
{
scanf("%s",a);
M[a]=i+1; //字符串转化为数字
}
for(int i=0;i<m;i++)
{
int fx,fy;
scanf("%d%s%s",&op,a,b);
fx=fi(M[a]);
fy=fi(M[b]);
if(op==1)
{
if(fx==fy) //祖先相同
{
if((R[M[a]]-R[M[b]]+2)%2==0)
printf("YES\n");
else
printf("NO\n");
}
else //祖先不同 将两棵树连起来
{
fa[fy]=fx;
R[fy]=(R[M[b]]-R[M[a]]+2)%2;
printf("YES\n");
}
}
else
{
if(fx==fy)
{
if((R[M[a]]-R[M[b]]+3)%2==0)
printf("YES\n");
else
printf("NO\n");
}
else
{
fa[fy]=fx;
R[fy]=(R[M[a]]-R[M[b]]+3)%2;
printf("YES\n");
}
}
}
while(q--)
{
scanf("%s%s",a,b);
int fx=fi(M[a]),fy=fi(M[b]);
if(fx!=fy)
printf("3\n");
else
{
printf("%d\n",(R[M[a]]+R[M[b]])%2+1);
}
}
}
}
版权声明:本文为weixin_44937448原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。