Advertisement
a53

politic1

a53
Dec 10th, 2019
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.36 KB | None | 0 0
  1. #include <cassert>
  2. #include <fstream>
  3. #include <algorithm>
  4. #include <vector>
  5.  
  6. using namespace std;
  7.  
  8. const int MAX_N = 1000;
  9.  
  10. // Input parameters
  11. int n;
  12. // Graph structure data
  13. int vNext[MAX_N + 1], visited[MAX_N + 1];
  14. vector<int> v[MAX_N + 1];
  15. // Cycle data
  16. bool inCycle[MAX_N + 1], rootCycle[MAX_N + 1];
  17. int cycleSize[MAX_N + 1];
  18. // DP data
  19. int maxOut[MAX_N + 1][MAX_N + 1], weight[MAX_N + 1];
  20. bool sel[MAX_N + 1];
  21.  
  22. void computeMaxOut(int node) {
  23. sel[node] = true;
  24.  
  25. assert((inCycle[node] ^ rootCycle[node]) == 0);
  26.  
  27. int rootCost = (inCycle[node] ? cycleSize[node] : 1), sons = 0;
  28. for (auto next : v[node])
  29. if (!sel[next] && !(inCycle[next] && !rootCycle[next]))
  30. sons++;
  31.  
  32. // if not in cycle, then the current node will be eliminated by the parent
  33. maxOut[node][rootCost] = (inCycle[node] ? rootCost : 0) + sons;
  34.  
  35. if (node == 0) { // eliminating the root does not cost anything and does not affect anything
  36. maxOut[node][rootCost] = 0;
  37. rootCost = 0;
  38. }
  39.  
  40. weight[node] = rootCost;
  41.  
  42. for (auto next : v[node])
  43. if (!sel[next] && !(inCycle[next] && !rootCycle[next])) { // don't go over other nodes in the cycle
  44. computeMaxOut(next);
  45. weight[node] += weight[next];
  46.  
  47. for (int i = weight[node]; i >= rootCost; i--) // total nodes
  48. for (int j = rootCost; j <= weight[node] - weight[next] && j < i; j++) // how much of it is the part already in node
  49. maxOut[node][i] = max(maxOut[node][i], maxOut[node][j] + maxOut[next][i - j]);
  50. }
  51. }
  52.  
  53. int main() {
  54. ifstream fin("politic.in");
  55. ofstream fout("politic.out");
  56.  
  57. // Read input.
  58. fin >> n;
  59.  
  60. assert(1 <= n && n <= MAX_N);
  61.  
  62. for (int i = 1; i <= n; i++) {
  63. fin >> vNext[i];
  64. v[vNext[i]].push_back(i); // keep reversed edges
  65.  
  66. assert(1 <= vNext[i] && vNext[i] <= n);
  67. }
  68.  
  69. // Detect cycles.
  70. for (int i = 1; i <= n; i++)
  71. if (!visited[i]) {
  72. visited[i] = i;
  73.  
  74. int node = i;
  75. while (!visited[vNext[node]]) {
  76. node = vNext[node];
  77. visited[node] = i;
  78. }
  79.  
  80. if (visited[vNext[node]] == i) { // have cycle
  81. rootCycle[node] = true;
  82. v[0].push_back(node); // edge from overall root (0) to cycle root node
  83.  
  84. int currentNode = node, currentCycleSize = 0;
  85. do {
  86. inCycle[currentNode] = true;
  87. currentCycleSize++;
  88.  
  89. if (currentNode != node) // merge sons
  90. for (auto next : v[currentNode])
  91. v[node].push_back(next);
  92.  
  93. currentNode = vNext[currentNode];
  94. } while (currentNode != node);
  95.  
  96. cycleSize[node] = currentCycleSize;
  97. }
  98. }
  99.  
  100. // Run DP.
  101. computeMaxOut(0);
  102.  
  103. // Get best result.
  104. int maximumOut = 0;
  105. for (int i = 1; i <= n; i++) {
  106. maximumOut = max(min(n, maximumOut + 1), maxOut[0][i]); // can use last result and eliminate one more node
  107. fout << n - maximumOut << '\n';
  108. }
  109.  
  110. fin.close();
  111. fout.close();
  112. return 0;
  113. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement