这是我参与「第三届青训营 -后端场」笔记创作活动的第5篇笔记
给你ABC三个排列,C的第i位为A或B的第i位,如果C【i】=0则为任意,否则C[i]为a,b中一个确定的数。
思路:
这题就是思想是并查集
-
先让Ai,Bi两个点相连,则形成的大的连通块中只要确定一个数,则其他所有数都确定。
-
如果a b相等,则这种情况相当于只能选一个,需要排除。
-
处理完连通块后,发现如果一个连通块中有一个i的c[i]确定,则整个连通块确定,如a[1]=2,b[1]=3,a[2]=3,b[2]=2,且c[1]=2时,c[2]只能等于3,整个连通块确定。
-
枚举剩下的连通块,每个连通块第第一个i有两种选法,剩下的确定,所以每有一个连通块,ans*=2;
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100010,mod=1e9+7;
int a[N],b[N],c[N],f[N];
bool v[N];
int find(int x){
if(x!=f[x])f[x]=find(f[x]);
return f[x];
}
int main(){
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int t;
cin>>t;
while(t--){
int n;
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
memset(v,0,sizeof(v));
cin>>n;
for(int i=1;i<=n;i++){
f[i]=i;
}
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<n;i++){
cin>>b[i];
}
for(int i=0;i<n;i++){
if(a[i]!=b[i]){
if(find(b[i])!=find(a[i]))f[find(a[i])]=find(b[i]);
}
else v[a[i]]=1;
}
for(int i=0;i<n;i++){
cin>>c[i];
if(c[i]!=0){
v[find(a[i])]=1;
}
}
int ans=1;
for(int i=0;i<n;i++){
if(v[find(a[i])]==0){
v[find(a[i])]=1;
ans=ans*2%mod;
}
**当时错因(思路):**
想到他们直接有关,但是想用dfs把这个连通块跑完,这样会很麻烦,而且会超时,主要还是并查集不熟悉。
**学习心得:**
加速操作:
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
查并集操作
**复习思路:**
}
cout<<ans%mod<<endl;
}
}