题目描述 :给你n个单词, 并且有m行每行有一个数字两个单词 数字代表之间的关系,2表示意思相反 ,1表示同义 之后有q行询问 每行两个单词 输出它两的关系
2 ≤ n ≤ 10^5, 1 ≤ m, q ≤ 10^5
分析:典型的带权并差集问题, 带1权值表示反义,0权值表示同义,在更新时用异或和维护他们之间的关系, 当合并时因为两个个方向走到尾 其异或和相等,而两者异或和为0 所以一个点的权值等去另外三个的异或和
ac代码
#include<bits/stdc++.h> using namespace std; const int MAX=2e5+3; int parent[MAX]; int value[MAX]; map<string,int> word; int find(int x){ if(x!=parent[x]){ int t=parent[x]; parent[x]=find(parent[x]); value[x]^=value[t]; } return parent[x]; } int main(){ // ios::sync_with_stdio(0); // cin.tie(0); // FILE *fp; // fp=fopen("1.txt","r"); int n,m,k; // fscanf(fp,"%d %d %d",&n,&m,&k); cin>>n>>m>>k; for(int i=1;i<=n;i++) parent[i]=i; memset(value,0,sizeof(value)); int ans=0; int t; for(int i=1;i<=n;i++){ string s; cin>>s; word[s]=i; } for(int i=1;i<=m;i++){ int a; string s,ss; cin>>a>>s>>ss; if(a==1) a=0; else a=1; int fs=find(word[s]),fss=find(word[ss]); if(fs!=fss){ parent[fs]=fss; // cout<<fs<<' '<<fss<<endl; value[fs]=value[word[s]]^value[word[ss]]^a; cout<<"YES"<<endl; } else if(value[word[s]]^value[word[ss]]!=a) cout<<"NO"<<endl; else cout<<"YES"<<endl; } for(int i=1;i<=k;i++){ string s,ss; cin>>s>>ss; int parents=find(word[s]),parentss=find(word[ss]); // cout<<"!!"<<parent[word[s]]<<' '<<parent[word[ss]]<<endl; if(parents==parentss) if(value[word[s]]^value[word[ss]]) cout<<2<<endl; else cout<<1<<endl; else cout<<3<<endl; } }