题意: 给定n,m,q 其中n位n个单词,m为m个关系,表示单词两两间的关系,其中关系有两种,分别为1和2,1表示同义词,2表示反义词。q个询问,询问两者间关系,若没关系,输出3.。
思路:根据题目信息,关系是分类的,分为1,2两种关系,如果关系不分类,那么就是并查集,如果关系分类,就是带权的并查集。
带权并查集学习参考自:http://blog.youkuaiyun.com/harlow_cheng/article/details/52737486
两两间关系1,2用0,1表示,则关系之间符合向量运算。
具体见注释。
#include<iostream>
#include<map>
#include<algorithm>
#include<string>
using namespace std;
map<string ,int> num;
int n, m, q;
int pre[100005], relation[100005];
string s1, s2;
int find(int x)
{
if(pre[x]==x)
{
return x;
}
int order=pre[x];
//路径压缩
pre[x]=find(pre[x]);
relation[x]=(relation[x]+relation[order])%2;//符合向量图运算
return pre[x];
}
int main()
{
cin >> n >> m >> q;
for(int i = 0; i < n; ++i)
{
cin >> s1;
num[s1] = i;
}
for(int i = 0; i < n; ++i)
{
pre[i] = i;
relation[i] = 0;
}
int x, y, z;
for(int i = 0; i < m; ++ i)
{
cin >> z >> s1 >> s2;
--z;
x = num[s1], y = num[s2];
int a = find(x), b = find(y);
if(a!=b)//关系还没有建立过
{
cout << "YES" << endl;
//更新结点值
pre[b]=a;
relation[b]=(relation[x]-relation[y]+z+2)%2; //+2防止出现负值
}
else
{
int p = (relation[x]-relation[y]+2)%2;
if(p == z) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
for(int i = 0; i < q; ++i)
{
cin >> s1 >> s2;
x = num[s1], y = num[s2];
int a = find(x), b = find(y);
if(a != b)
cout << "3" << endl;
else
cout << (relation[x] - relation[y] + 2)%2 +1 << endl;
}
return 0;
}