• Pavel and barbecue


    题目链接

    CF756A

    题目

    Pavel cooks barbecue. There are n skewers, they lay on a brazier in a row, each on one of n positions. Pavel wants each skewer to be cooked some time in every of n positions in two directions: in the one it was directed originally and in the reversed direction.

    Pavel has a plan: a permutation p and a sequence b 1, b 2, ..., b n, consisting of zeros and ones. Each second Pavel move skewer on position i to position p i, and if b i equals 1 then he reverses it. So he hope that every skewer will visit every position in both directions.

    Unfortunately, not every pair of permutation p and sequence b suits Pavel. What is the minimum total number of elements in the given permutation p and the given sequence b he needs to change so that every skewer will visit each of 2n placements? Note that after changing the permutation should remain a permutation as well.

    There is no problem for Pavel, if some skewer visits some of the placements several times before he ends to cook. In other words, a permutation p and a sequence b suit him if there is an integer k ( k ≥ 2n), so that after k seconds each skewer visits each of the 2n placements.

    It can be shown that some suitable pair of permutation p and sequence b exists for any n.

    Input
    The first line contain the integer (n (1 ≤ n ≤ 2·10^5)) — the number of skewers.

    The second line contains a sequence of integers (p_1, p_2, ..., p_n (1 ≤ p_i ≤ n)) — the permutation, according to which Pavel wants to move the skewers.

    The third line contains a sequence (b_1, b_2, ..., b_n) consisting of zeros and ones, according to which Pavel wants to reverse the skewers.

    Output
    Print single integer — the minimum total number of elements in the given permutation p and the given sequence b he needs to change so that every skewer will visit each of 2n placements.

    Examples
    Input

    4
    4 3 2 1
    0 1 1 1
    

    Output

    2
    

    Input

    3
    2 3 1
    0 0 0
    

    Output

    1
    

    Note
    In the first example Pavel can change the permutation to 4, 3, 1, 2.

    In the second example Pavel can change any element of b to 1.

    题意

    有n个位置和n个肉串,需要把每个串串在每个地方两面都烤过才可以吃,现在有一个序列p,(p_i)表示在放在i的肉串下一个都被放到(p_i)。有序列b,当(b_i)为1时,这个位置要进行翻面。让你对p和b的元素进行最少的修改,让所有肉串都能吃。

    思路

    • 理解一下第一个样例的NOTE的4,3,1,2:

      • 对于第一个位置的肉串:1->4->2->3->1->4->2->3->1...,于此同时翻面:0->1->0->1->1->0->1->0->0->...。 第二个:2->3->1->4->2->3->1->4->2...,...
      • 每个肉串都正反两面在所有地方烤了。
      • 观察看看,有环,而且两个环里面正反面不同。
    • 让每个肉串在每个地方烤过

      • 意思就是p可以成一个环,这样每个地方的肉串都可以绕一圈又一圈,去到每个地方。
      • 判断环可以用dfs
      • 对于原来给的p序列,不能成一个环的话,会成多个环,例如样例1的p会成两个环。我们的目标是一个环,所以要将多个环合成一个环。观察一下,就可以发现,x个环合成一个环最少要修改x条边。每个环修改一条。
      • 注意如果本身就1个环的话,就不需要修改了,否则有多少环修改多少次。
    • 让每个肉串在每个地方两面都烤过

      • 意思就是一个环绕两圈,这一圈的每个面要和上一圈的面不一样。
      • 要让第二圈的面和第一圈的面不同,那么第一次绕回原点的时候,原点的面应该和一开始的时候的面不一样了,要实现这个,就只要保证这一圈中翻面的次数是奇数就好了。
      • 如果翻面次数是偶数,那修改次数要+1,用来增加/减少一次翻面。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=200005;
    int n;
    int p[MAXN],b[MAXN];
    bool vis[MAXN];
    void dfs(int x){
    	while(!vis[x]){
    		vis[x]=true;
    		x=p[x];
    	}
    }
    int main(){
    	scanf("%d",&n);
    	int ans=0;
    	for(int i=1;i<=n;i++) scanf("%d",&p[i]);
    	int cnt=0;
    	for(int i=1;i<=n;i++){
    		scanf("%d",&b[i]);
    		if(b[i]==1) cnt++;
    	}
    	if(cnt%2==0) ans++;
    	cnt=0;
    	for(int i=1;i<=n;i++){
    		if(vis[i]) continue;
    		dfs(i);
    		cnt++;
    	}
    	if(cnt!=1) ans+=cnt;
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    删除表数据drop、truncate和delete的用法
    List,DataTable实现行转列的通用方案
    C#正则表达式简单限制输入11位手机号
    Oracle数据库byte存放汉字,9个汉字x3=27个字节
    SQL 语句
    $("p").fadeOut("fast")设置淡出效果
    神奇的 toLocaleString
    C#中精确计时的一点收获
    Web service stop after running serveral hours
    SQL Server中like匹配下划线的方法
  • 原文地址:https://www.cnblogs.com/xuwanwei/p/12833841.html
Copyright © 2020-2023  润新知