数据结构之对于一道思维题的思考

49 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第5篇笔记

题目: C. Where is the Pizza?

题目大意:

给你ABC三个排列,C的第i位为A或B的第i位,如果C【i】=0则为任意,否则C[i]为a,b中一个确定的数。

完整题目

image.png

image.png

image.png 思路:

这题就是思想是并查集

  1. 先让Ai,Bi两个点相连,则形成的大的连通块中只要确定一个数,则其他所有数都确定。

  2. 如果a b相等,则这种情况相当于只能选一个,需要排除。

  3. 处理完连通块后,发现如果一个连通块中有一个i的c[i]确定,则整个连通块确定,如a[1]=2,b[1]=3,a[2]=3,b[2]=2,且c[1]=2时,c[2]只能等于3,整个连通块确定。

  4. 枚举剩下的连通块,每个连通块第第一个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;

}

}