Codeforces Round #393 (Div. 2) - C
题目链接:http://codeforces.com/contest/760/problem/C
题意:有n个烤串,并且每个烤串起初都放在一个火盆上并且烤串都正面朝上,现在定义p序列,p[i]表示在i位置的烤串下一步会转移到p[i]位置的火盆上;定义b序列,
b[i]为1表示每有烤串移动到i火盆上时,该烤串就要翻面。 现在要求n个烤串每个烤串都要经过所有的火盆并且最终回到自己初始的火盆上并且翻面朝上。 求最少的
序列修改。
思路:首先考虑让每一个烤串都要经过所有的火盆并且回到起初的火盆,那么p序列只能是环,由于输入的p序列可能形成多个环,那么把多个环合并成一个环最少要修改的次数为环的数目(特判只有一个环的时候,因为只有一个环不需要修改)。接下来考虑最终要翻面朝上,由于n个位置都要经过所以如果sum(b[i])为偶数,那么最终肯定还是正面,所以只需让sum(b[i])为奇数即可。
import java.io.PrintWriter; import java.util.*; public class Main { public static final int MAXN=200000+10; public static int p[]=new int [MAXN]; public static int b[]=new int [MAXN]; public static boolean vis[]=new boolean [MAXN]; public static void dfs(int u){ if(vis[u]==true){ return; } vis[u]=true; dfs(p[u]); } public static void main(String[] args) { Scanner cin = new Scanner(System.in); PrintWriter out = new PrintWriter(System.out); int n=cin.nextInt(); for(int i=1;i<=n;i++){ p[i]=cin.nextInt(); } int sumb=0; for(int i=1;i<=n;i++){ b[i]=cin.nextInt(); sumb+=b[i]; } int ans=0; Arrays.fill(vis, false); for(int i=1;i<=n;i++){ if(vis[i]==false){ ans++; dfs(i); } } if(ans!=1){ ans=ans+(sumb%2==1?0:1); }else{ ans=(sumb%2==1?0:1); } out.println(ans); cin.close(); out.flush(); } }