C. Where is the Pizza?
提供一种思路:
首先我们可以思考,假如c[i]
是定下来的,那么a[i]
和b[i]
中有一个等于c[i]
,我们假设 这个数是a[i]
,那么后面的a
和b
数组里面出现的b[j] = a[i]
这个b[j]
是不能被选的,只能选择a[j]
以此类推,部分位置的选法是确定的。 我们可以双向建边a[i] -> b[i]
和b[i] -> a[i]
,这样可能会出现长度大于2
的环,当环上有一个点的位置是确定的话,那么这个环上的选法就是确定的,当我们把所有的环的情况理出来后,假如剩下cnt
个位置,答案就是
2
c
n
t
2^{cnt}
2cnt。
和本题类似的一题:B2. Books Exchange (hard version)
这场 d i v 3 div3 div3之前就vp过,但是写这题的时候没能想到做过类似的,虽然能写出来,但是感觉是无效刷题,还是要多写总结呀。大哭(
int h[N], ne[N * 2], e[N * 2], idx;
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void dfs(int u){
st[u] = true;
for(int i = h[u]; ~i; i = ne[i]){
int j = e[i];
if(!st[j]) dfs(j);
}
}
void solve()
{
idx = 0;
n = read();
for(int i = 1; i <= 2 * n; i ++ ) h[i] = -1;
for(int i = 1; i <= n; i ++ ) a[i] = read();
for(int i = 1; i <= n; i ++ ){
b[i] = read();
st[i] = false;
}
for(int i = 1; i <= n; i ++ ){
if(a[i] != b[i]){
add(a[i], b[i]);
add(b[i], a[i]);
}else{
st[a[i]] = true;
}
}
for(int i = 1; i <= n; i ++ ){
c[i] = read();
if(c[i]){
st[c[i]] = true;
dfs(c[i]);
}
}
long long cnt = 1;
for(int i = 1; i <= n; i ++ ){
if(!st[a[i]] && !st[b[i]]) cnt *= 2ll , cnt = cnt % mod;
if(!st[a[i]] || !st[b[i]]){
dfs(a[i]);
}
}
write(cnt);
putchar('\n');
}