题意:
给出n个单词,m条插入,每条插入包括两个单词,和单词之间的关系(近义词,反义词),
如果目前要插入的和已知的相矛盾,则取消插入
q条询问,询问两个单词的关系,近义词输出1,反义词输出2,不知道输出3
题解:
用并查集来做,如果两个词是近义词,则合并(a,b)和(a+n,b+n),如果是反义词则合并(a,b+n)和(a+n,b)
如果两个词有相同的父节点,也就是(a,b)在一组或者(a+n,b+n)在一组,则输出1,
如果(a,b+n)或者(a+n,b)在一组,则输出2,此外输出3
1 # include <cstdio> 2 # include <iostream> 3 # include <cstring> 4 # include <algorithm> 5 # include <map> 6 # include <string> 7 using namespace std; 8 9 const int maxn=1e5+5; 10 int n,m,q; 11 int c; 12 string a,b; 13 map <string,int> mm; 14 int par[maxn*3+5]; 15 int mark[maxn]; 16 17 int findd(int x){ 18 if(par[x]==x) return x; 19 else return par[x]=findd(par[x]); 20 } 21 22 void unit(int x,int y){ 23 x=findd(x); 24 y=findd(y); 25 par[x]=y; 26 } 27 28 bool same(int x,int y){ 29 return findd(x)==findd(y); 30 } 31 32 int main(){ 33 while(scanf("%d%d%d",&n,&m,&q)!=EOF){ 34 for(int i=1;i<=n;i++){ 35 cin>>a; 36 mm[a]=i; 37 par[i]=i; 38 par[i+n]=i+n; 39 } 40 memset(mark,0,sizeof(mark)); 41 for(int i=1;i<=m;i++){ 42 cin>>c>>a>>b; 43 if(c==1) { 44 if(same(mm[a],mm[b]+n)) { 45 printf("NO "); 46 continue; 47 } 48 if(same(mm[a]+n,mm[b])) { 49 printf("NO "); 50 continue; 51 } 52 printf("YES "); 53 unit(mm[a]+n,mm[b]+n); 54 unit(mm[a],mm[b]); 55 mark[mm[a]]=mark[mm[b]]=1; 56 //cout<<par[1]<<par[2]<<par[3]<<endl; 57 } 58 else { 59 if(same(mm[a],mm[b])) { 60 printf("NO "); 61 continue; 62 } 63 if(same(mm[a]+n,mm[b]+n)) { 64 printf("NO "); 65 continue; 66 } 67 printf("YES "); 68 unit(mm[a]+n,mm[b]); 69 unit(mm[a],mm[b]+n); 70 mark[mm[a]]=mark[mm[b]]=1; 71 //cout<<par[1]<<par[2]<<par[3]<<endl; 72 } 73 } 74 for(int i=1;i<=q;i++){ 75 cin>>a>>b; 76 if(same(mm[a],mm[b])) printf("1 "); 77 else if(same(mm[a],mm[b]+n)||same(mm[a]+n,mm[b]))printf("2 "); 78 else printf("3 "); 79 } 80 } 81 return 0; 82 }