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 

#include <bits/stdc++.h>
using namespace std;
struct outFloat {
  int precision;
  long double value;
  outFloat(long double v, int p) : precision(p), value(v) {}
};
template <typename T>
struct debugInfo {
  string name;
  T val;
  debugInfo(const char* n, T v) : name(n), val(v){};
};
template <typename T>
debugInfo<T> makeDebugInfo(const char* n, T v) {
  return debugInfo<T>(n, v);
}
const int inf = 123456789;
const long long llInf = 123456789012345678LL;
const long double pi = 3.14159265358979323846;
const int maxN = 2000000;
int init() {
  ios_base::sync_with_stdio(0);
  srand(time(NULL));
  return 0;
}
int initializer = init();
template <typename T1, typename T2>
istream& operator>>(istream& is, pair<T1, T2>& p) {
  is >> p.first >> p.second;
  return is;
}
template <typename T>
istream& operator>>(istream& is, vector<T>& p) {
  for (int i = 0; i < p.size(); i++) is >> p[i];
  return is;
}
class inputer {
 private:
  istream* istr;

 public:
  inputer(istream& is) : istr(&is) {}
  template <typename T>
  void get(T& n) {
    (*istr) >> n;
  }
  template <typename T, typename... Args>
  void get(T& n, Args&... args) {
    get(n);
    get(args...);
  }
  template <typename... Args>
  void getLn(Args&... args) {
    get(args...);
    getLn();
  }
  template <typename T>
  operator T() {
    T n;
    get(n);
    return n;
  }
  void getLn() {
    string s;
    getline(cin, s);
  }
  template <typename T>
  void getv(vector<T>& v, int size) {
    v.resize(size);
    (*istr) >> v;
  }
};
string delim = " ";
template <typename T1, typename T2>
ostream& operator<<(ostream& os, const pair<T1, T2>& p) {
  os << p.first << delim << p.second;
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const vector<T>& p) {
  for (int i = 0; i < p.size(); i++) {
    if (i != 0) os << delim;
    os << p[i];
  }
  return os;
}
ostream& operator<<(ostream& os, const outFloat& of) {
  os << setprecision(of.precision) << of.value;
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const debugInfo<T>& dbg) {
  os << "\"" << dbg.name << "\" = \"" << dbg.val << "\""
     << "\n";
}
class outputer {
 private:
  ostream* ostr;

 public:
  outputer(ostream& os) : ostr(&os) {}
  template <typename T>
  void put(const T& n) {
    (*ostr) << n;
  }
  template <typename T, typename... Args>
  void put(const T& n, const Args&... args) {
    put(n);
    put(args...);
  }
  template <typename... Args>
  void putLn(const Args&... args) {
    put(args...);
    putLn();
  }
  template <typename T>
  outputer& operator=(const T& n) {
    putLn(n);
    return *this;
  }
  void putLn() { (*ostr) << "\n"; }
  template <typename T>
  void putv(vector<T> v, int size, string delim) {
    for (int i = 0; i < size; i++) {
      if (i != 0) (*ostr) << delim;
      (*ostr) << v[i];
    }
  }
};
inputer in(cin);
outputer out(cout);
char getChar() {
  char c = 0;
  while (c <= ' ') cin >> c;
  return c;
}
bool willItBeAC() {
  return true;
  ;
}
int getMyRating() { return 2048; }
bool prime(long long n) {
  for (long long i = 2; i * i <= n; i++)
    if (n % i == 0) return false;
  return true;
}
vector<long long> divs(long long n) {
  vector<long long> v;
  long long i = 2;
  while (i * i <= n)
    if (n % i == 0) {
      n /= i;
      v.push_back(i);
    } else
      i++;
  v.push_back(n);
  return v;
}
long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }
long long extGcd(long long a, long long b, long long& x, long long& y) {
  if (a == 0) {
    x = 0;
    y = 1;
    return b;
  }
  long long x1, y1, d = extGcd(b % a, a, x1, y1);
  x = y1 - (b / a) * x1;
  y = x1;
  return d;
}
template <typename T>
class fenwick {
 private:
  vector<T> t;
  int n;

 public:
  fenwick(int nn) { init(nn); }
  void init(int nn) {
    n = nn;
    t.assign(n, 0);
  }
  T sum(int r) {
    T result = 0;
    for (; r >= 0; r = (r & (r + 1)) - 1) result += t[r];
    return result;
  }
  void inc(int i, T delta) {
    for (; i < n; i = (i | (i + 1))) t[i] += delta;
  }
  T sum(int l, int r) { return sum(r) - sum(l - 1); }
  T get(int i) { return sum(i, i); }
  void put(int i, T v) { inc(i, v - sum(i, i)); }
  int size() { return n; }
};
int n = in;
int cnt = 0;
vector<int> q, tQ;
vector<char> used(n, false);
vector<vector<int> > g(n);
vector<int> roots;
int ses = 0;
void dfs(int v, int sID) {
  used[v] = sID;
  for (int i = 0; i < (int)g[v].size(); i++) {
    int to = g[v][i];
    if (used[to] == sID)
      q[to] = -1;
    else if (used[to])
      break;
    else
      dfs(to, sID);
  }
}
int main() {
  in.getv(q, n);
  tQ = q;
  for (int i = 0; i < n; i++) q[i]--;
  for (int i = 0; i < n; i++)
    if (q[i] == i)
      roots.push_back(i);
    else
      g[q[i]].push_back(i);
  for (int i : roots) dfs(i, ses++);
  for (int i = 0; i < n; i++)
    if (!used[i]) dfs(i, ses++);
  int fM1 = -1;
  for (int i = 0; i < n; i++)
    if (q[i] < 0) fM1 = i;
  for (int i = 0; i < n; i++)
    if (q[i] == i) q[i] = -1;
  if ((int)roots.size() == 0) roots.push_back(fM1);
  for (int i = 0; i < n; i++)
    if (q[i] < 0) q[i] = roots[0];
  for (int i = 0; i < n; i++) q[i]++;
  for (int i = 0; i < n; i++)
    if (tQ[i] != q[i]) cnt++;
  out = cnt;
  out = q;
  return 0;
}
