3
2 1 1
 6
6 2 6 2 4 2
 2
1 2
 8
2 1 2 2 6 5 6 6
 18
2 3 4 5 2 7 8 9 10 7 11 12 14 15 13 17 18 18
 7
1 2 3 4 5 6 7
 7
4 3 2 6 3 5 2
 7
7 5 3 1 2 1 5
 7
1 6 4 4 5 6 7

1
2 2 1  0
6 2 6 2 4 2  1 
1 1 
 2 
2 2 2 2 6 2 6 6 
 5 
2 3 4 5 11 7 8 9 10 11 11 11 14 15 11 17 18 11 
 6 
1 1 1 1 1 1 1 
 1
4 3 3 6 3 5 2  1
7 5 3 1 3 1 5  4 
1 6 4 1 1 1 1 

import java.io.*;
import java.util.*;
import java.lang.Math;
import java.math.BigInteger;

import com.sun.corba.se.impl.encoding.OSFCodeSetRegistry.Entry;

public class Problem {

	public static void main(String[] args) throws IOException {

		new Problem().run();
	}

	BufferedReader in;
	PrintWriter out;
	StringTokenizer tok;
	Random rnd = new Random();
	static final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null;

	Problem() throws FileNotFoundException {

		if (ONLINE_JUDGE) {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);
		} else {
			in = new BufferedReader(new FileReader("input.txt"));
			out = new PrintWriter("output.txt");
		}
		tok = new StringTokenizer("");
	}

	List<Integer>[] graph;
	boolean[] used;
	int[] ans;
	int[] colors;
	int counter=0;
	ArrayList<Integer> roots = new ArrayList<>();
	int main_root=-1;
	void solve() throws IOException {
		
		int n = rI();
		graph = new ArrayList[n];
		used = new boolean[n];
		colors = new int[n];
		ans = new int[n];
		
		for(int i=0;i<n;++i){
			graph[i] = new ArrayList<>();
		}
		for(int i=0;i<n;++i){
			ans[i] = rI()-1;
			if(i!=ans[i]){
				graph[i].add(ans[i]);
			}else{
				roots.add(i);
			}
		}
		
		for(int i=0;i<n;++i){
			if(ans[i]==i){
				main_root=i;
			}
		}
		for(int i=0;i<n;++i){
			if(colors[i]==0){
				dfs(i);
			}
		}
		
		out.println(counter);
		for(int a: ans){
			out.print(a+1+" ");
		}

	}
	void dfs(int from){
		colors[from] = 1;
		if(ans[from]!=from){
			for(int to: graph[from]){
				if(colors[to]==0){
					dfs(to);
				}else if(colors[to]==1){
					if(main_root==-1){
						ans[from] = from;
						main_root=from;
						counter++;
					}else{
						ans[from] = main_root;
						counter++;
					}
				}
			}
		}else{
			if(ans[from]!=main_root){
				ans[from] = main_root;
				counter++;
			}
		}
		
		colors[from] = 2;
	}
	// ======================================================
	class SegmentTree {

		int[] tree;

		SegmentTree(int n) {
			tree = new int[n];
		}

		void build(int[] a, int v, int curL, int curR) {
			if (curL == curR) {
				this.tree[v] = a[curL];
			} else {
				int mid = (curL + curR) / 2;
				build(a, v * 2, curL, mid);
				build(a, v * 2 + 1, mid + 1, curR);
				this.tree[v] = this.tree[v * 2] + this.tree[v * 2 + 1];
			}
		}

	}

	class Dsu {
		int[] parents;
		int countUnions;

		Dsu(int size) {
			this.parents = new int[size];
			for (int i = 0; i < size; ++i) {
				parents[i] = i;
			}
			this.countUnions = size;
		}

		int get(int v) {
			if (v == parents[v])
				return v;
			return parents[v] = get(parents[v]);
		}

		boolean union(int a, int b) {
			a = get(a);
			b = get(b);
			if (a == b) {
				return false;
			}
			if (rnd.nextBoolean()) {
				parents[a] = b;
			} else {
				parents[b] = a;
			}
			this.countUnions--;
			return true;
		}
	}

	// ======================================================
	void run() throws IOException {
		solve();
		out.close();
	}

	char[] reverseCharArray(char[] arr) {
		char[] ans = new char[arr.length];
		for (int i = 0; i < arr.length; ++i) {
			ans[i] = arr[arr.length - i - 1];
		}
		return ans;
	}

	int sqrt(double m) {
		int l = 0;
		int r = 1000000000 + 9;
		int i = 1000;
		while (r - l > 1) {
			int mid = (r + l) / 2;
			if (mid * mid > m) {
				r = mid;
			} else {
				l = mid;
			}
		}
		return l;
	}

	int countPow(int m, int n) {
		int ans = 0;
		while (m % n == 0 && m > 0) {
			ans++;
			m /= n;
		}
		return ans;
	}

	long binPow(long a, long b) {
		if (b == 0) {
			return 1;
		}
		if (b % 2 == 1) {
			return a * binPow(a, b - 1);
		} else {
			long c = binPow(a, b / 2);
			return c * c;
		}

	}

	long gcd(long a, long b) {
		return b == 0 ? a : gcd(b, a%b);
	}

	long pow(long x, long k) {
		long ans = 1;
		for (int i = 0; i < k; ++i) {
			ans *= x;
		}
		return ans;
	}

	// ////////////////////////////////////////////////////////////////////

	String delimiter = " ";

	String readLine() throws IOException {
		return in.readLine();
	}

	String rS() throws IOException {
		while (!tok.hasMoreTokens()) {
			String nextLine = readLine();
			if (null == nextLine)
				return null;

			tok = new StringTokenizer(nextLine);
		}

		return tok.nextToken(delimiter);
	}

	int rI() throws IOException {
		return Integer.parseInt(rS());
	}

	long rL() throws IOException {
		return Long.parseLong(rS());
	}

	int[] rA(int b) {
		int a[] = new int[b];
		for (int i = 0; i < b; i++) {
			try {
				a[i] = rI();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return a;
	}

	int[] readSortedIntArray(int size) throws IOException {
		Integer[] array = new Integer[size];

		for (int index = 0; index < size; ++index) {
			array[index] = rI();
		}
		Arrays.sort(array);

		int[] sortedArray = new int[size];
		for (int index = 0; index < size; ++index) {
			sortedArray[index] = array[index];
		}

		return sortedArray;
	}

	int[] sortedIntArray(int size, int[] array) throws IOException {
		for (int index = 0; index < size; ++index) {
			array[index] = rI();
		}
		Arrays.sort(array);

		int[] sortedArray = new int[size];
		for (int index = 0; index < size; ++index) {
			sortedArray[index] = array[index];
		}

		return sortedArray;
	}
}