#include <bits/stdc++.h>
volatile bool isLocalTestEnabled = 0;
bool g_isLocalPrintEnabled = (bool)(0);
template <typename T>
void UpdateMin(T& a, const T b) {
  a = std::min(a, b);
}
template <typename T>
void UpdateMax(T& a, const T b) {
  a = std::max(a, b);
}
const long double Pi = std::atan(1.0L) * 4.0L;
static const long double Eps = 1.0e-09;
template <typename T>
bool IsEqual(const T a, const T b) {
  return std::abs(a - b) < Eps;
}
template <typename T>
bool IsGreater(const T a, const T b) {
  return a > b + Eps;
}
template <typename T>
bool IsLess(const T a, const T b) {
  return a + Eps < b;
}
template <typename T>
bool IsGreaterEqual(const T a, const T b) {
  return !IsLess(a, b);
}
template <typename T>
bool IsLessEqual(const T a, const T b) {
  return !IsGreater(a, b);
}
template <typename T>
std::string ToStr(const T& val) {
  std::ostringstream ostr;
  ostr << val;
  return ostr.str();
}
template <typename T>
bool FromStr(const std::string& str, T& val) {
  std::istringstream istr(str);
  istr >> val;
  return !!istr;
}
template <typename T>
std::istream& operator>>(std::istream& ist, std::vector<T>& data) {
  ;
  for (size_t i = 0; i < data.size(); i++) {
    ist >> data[i];
  }
  return ist;
}
template <typename T>
T Read(std::istream& ist) {
  ;
  T val;
  ist >> val;
  return val;
}
template <typename T>
std::ostream& operator<<(std::ostream& ost, const std::vector<T>& data) {
  for (size_t i = 0; i < data.size(); i++) {
    if (i != 0) {
      ost << ' ';
    }
    ost << data[i];
  }
  return ost;
}
template <size_t id>
class StopWatch {};
enum PartType { Loop = 1, Tree = 2 };
void Dfs(const std::vector<std::vector<size_t> >& undirectedLinks,
         const size_t start, std::vector<size_t>& isVisited,
         std::vector<size_t>& part) {
  ;
  isVisited[start] = 1;
  part.push_back(start);
  for (size_t i = 0; i < undirectedLinks[start].size(); i++) {
    const size_t next = undirectedLinks[start][i];
    if (isVisited[next]) continue;
    Dfs(undirectedLinks, next, isVisited, part);
  }
}
PartType GetPartType(const std::vector<size_t>& part,
                     const std::vector<size_t>& p, size_t& treeRoot) {
  size_t loopCount = 0;
  for (size_t i = 0; i < part.size(); i++) {
    const size_t vertex = part[i];
    if (p[vertex] == vertex) {
      loopCount += 1;
      treeRoot = vertex;
    }
  }
  if (loopCount == 0) return Loop;
  ;
  return Tree;
}
void DfsLoop(const std::vector<std::vector<size_t> >& undirectedLinks,
             const size_t prev, const size_t start,
             std::map<size_t, size_t>& isVisited, size_t& loopPoint) {
  ;
  isVisited[start] = 1;
  for (size_t i = 0; i < undirectedLinks[start].size(); i++) {
    const size_t next = undirectedLinks[start][i];
    if (isVisited[next]) {
      if (next != prev) loopPoint = next;
      continue;
    }
    DfsLoop(undirectedLinks, start, next, isVisited, loopPoint);
  }
}
size_t GetLoopPoint(const std::vector<std::vector<size_t> >& undirectedLinks,
                    const std::vector<size_t>& p,
                    const std::vector<size_t>& part) {
  for (size_t i = 0; i < part.size(); i++) {
    const size_t vertex = part[i];
    if (p[p[vertex]] == vertex) return vertex;
  }
  const size_t n = undirectedLinks.size();
  size_t loopPoint = n;
  std::map<size_t, size_t> isVisited;
  DfsLoop(undirectedLinks, part[0], part[0], isVisited, loopPoint);
  ;
  return loopPoint;
}
bool Solve(std::istream& ist, std::ostream& ost, const bool multipleTestMode) {
  StopWatch<1> sw;
  (void)sw;
  size_t n;
  ist >> n;
  if (multipleTestMode && !ist) return false;
  if (!g_isLocalPrintEnabled) {
  } else
    std::cerr << std::endl << "Next test" << std::endl;
  std::vector<size_t> p(n);
  for (size_t i = 0; i < n; i++) {
    ist >> p[i];
    --p[i];
  }
  std::vector<std::vector<size_t> > undirectedLinks(n);
  for (size_t i = 0; i < n; i++) {
    undirectedLinks[p[i]].push_back(i);
    undirectedLinks[i].push_back(p[i]);
  }
  std::vector<std::vector<size_t> > parts;
  std::vector<PartType> partTypes;
  std::vector<size_t> subtreeRoots;
  {
    std::vector<size_t> isVisited(n);
    for (size_t i = 0; i < n; i++) {
      if (isVisited[i]) continue;
      std::vector<size_t> part;
      Dfs(undirectedLinks, i, isVisited, part);
      size_t subtreeRoot = n;
      const PartType type = GetPartType(part, p, subtreeRoot);
      parts.push_back(part);
      partTypes.push_back(type);
      subtreeRoots.push_back(subtreeRoot);
    }
  }
  size_t firstTree = n;
  bool hasTree = false;
  for (size_t i = 0; i < parts.size(); i++) {
    if (partTypes[i] == Tree) {
      hasTree = true;
      firstTree = i;
      break;
    }
  }
  size_t replacements = 0;
  std::vector<size_t> ans = p;
  if (hasTree) {
    std::swap(parts[firstTree], parts[0]);
    std::swap(partTypes[firstTree], partTypes[0]);
    std::swap(subtreeRoots[firstTree], subtreeRoots[0]);
  } else {
    const size_t treeRoot = GetLoopPoint(undirectedLinks, p, parts[0]);
    ans[treeRoot] = treeRoot;
    replacements += 1;
  }
  for (size_t i = 1; i < parts.size(); i++) {
    if (partTypes[i] == Tree) {
      const size_t currPartVertex = subtreeRoots[i];
      ;
      const size_t prevPartVertex = parts[i - 1][0];
      ans[currPartVertex] = prevPartVertex;
    } else {
      ;
      const size_t currPartVertex = GetLoopPoint(undirectedLinks, p, parts[i]);
      ;
      const size_t prevPartVertex = parts[i - 1][0];
      ans[currPartVertex] = prevPartVertex;
    }
    replacements += 1;
  };
  for (size_t i = 0; i < n; i++) {
    ans[i] += 1;
  }
  ost << replacements << std::endl;
  ost << ans << std::endl;
  return multipleTestMode;
}
int main(int argc, const char* argv[]) {
  std::ios_base::sync_with_stdio(false);
  std::istream* ist = &std::cin;
  std::ostream* ost = &std::cout;
  std::unique_ptr<std::istream> fileInput;
  if (argc > 1) {
    fileInput.reset(new std::ifstream(argv[1]));
    if (!(*fileInput)) {
      std::cout << "File not found: " << argv[1] << std::endl;
    }
    ist = fileInput.get();
  }
  Solve(*ist, *ost, false);
}
