Advertisement
Guest User

Untitled

a guest
Aug 8th, 2017
283
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.30 KB | None | 0 0
  1. import java.io.BufferedReader;
  2. import java.io.BufferedWriter;
  3. import java.io.FileReader;
  4. import java.io.FileWriter;
  5. import java.io.PrintWriter;
  6. import java.util.ArrayList;
  7. import java.util.HashSet;
  8. import java.util.StringTokenizer;
  9.  
  10.  
  11. public class grass {
  12. /*
  13. * grass cownoisseur
  14. */
  15.  
  16. /*
  17. * algo:
  18. * first find all SCCs
  19. * then toposort
  20. * then DFS down and count cows longest paths. If current node in dfs has parent that is ancestor of node containing barn, then we DFS that node too and eliminate the up arrow
  21. */
  22. static final int infinity = -1000000;
  23. static boolean[] visited;
  24. static int[] id;
  25. static int[] lowlink;
  26. static int pre;
  27. static int count = 0;
  28. static ArrayList<Integer> stack;
  29.  
  30.  
  31. public static void tarjan(Vertex[] vertices) {
  32. visited = new boolean[vertices.length];
  33. stack = new ArrayList<Integer>();
  34. id = new int[vertices.length];
  35. lowlink = new int[vertices.length];
  36. for (int v = 0; v < vertices.length; v++) {
  37. if (!visited[v]) tarjandfs(vertices, v);
  38. }
  39. }
  40.  
  41. public static void tarjandfs(Vertex[] vertices, int v) {
  42. visited[v] = true;
  43. lowlink[v] = pre++;
  44. int min = lowlink[v];
  45. stack.add(v);
  46. for (Vertex w : vertices[v].adjacents) {
  47. if (!visited[w.number]) tarjandfs(vertices, w.number);
  48. if (lowlink[w.number] < min) min = lowlink[w.number];
  49. }
  50. if (min < lowlink[v]) {
  51. lowlink[v] = min;
  52. return;
  53. }
  54. int w;
  55. do {
  56. w = stack.remove(stack.size() - 1);
  57. id[w] = count;
  58. lowlink[w] = vertices.length;
  59. } while (w != v);
  60. count++;
  61. }
  62.  
  63. public static void main(String[] args) throws Exception {
  64. //BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
  65. //PrintWriter w = new PrintWriter(System.out);
  66.  
  67. BufferedReader r = new BufferedReader(new FileReader("grass.in"));
  68. PrintWriter w = new PrintWriter(new BufferedWriter(new FileWriter("grass.out")));
  69.  
  70. StringTokenizer st = new StringTokenizer(r.readLine());
  71. int n = Integer.parseInt(st.nextToken());
  72. int m = Integer.parseInt(st.nextToken());
  73.  
  74.  
  75. Vertex[] initialGraph = new Vertex[n];
  76. for (int i = 0; i < initialGraph.length; i++) {
  77. initialGraph[i] = new Vertex(i);
  78. }
  79.  
  80. for (int i = 0; i < m; i++) {
  81. st = new StringTokenizer(r.readLine());
  82.  
  83. int a = Integer.parseInt(st.nextToken()) - 1;
  84. int b = Integer.parseInt(st.nextToken()) - 1;
  85.  
  86. initialGraph[a].addPath(initialGraph[b], 1);
  87. }
  88.  
  89. //run tarjan
  90.  
  91. tarjan(initialGraph);
  92.  
  93. int[] components = new int[count];
  94. for (int i = 0; i < id.length; i++) {
  95. components[id[i]]++;
  96. }
  97.  
  98. int uniquescc = count;
  99.  
  100. Vertex[] vertices = new Vertex[uniquescc];
  101.  
  102. for (int i = 0; i <vertices.length; i++) {
  103. vertices[i] = new Vertex(i);
  104. vertices[i].pastureCount = components[i];
  105. }
  106. Vertex barn = vertices[id[0]];
  107.  
  108. for (int i = 0; i < initialGraph.length; i++) {
  109. for (int j = 0; j < initialGraph[i].adjacents.size(); j++) {
  110. //If i is not in the same connected component as neighbor j
  111. int icomponent = id[i];
  112. int jcomponent = id[initialGraph[i].adjacents.get(j).number];
  113. if (icomponent != jcomponent) {
  114. //add the path
  115. //if we haven't already added the path
  116. if (!vertices[icomponent].alreadyAdded.contains(vertices[jcomponent])) {
  117. vertices[icomponent].addPath(vertices[jcomponent], vertices[jcomponent].pastureCount);
  118. vertices[jcomponent].addParent(vertices[icomponent], vertices[icomponent].pastureCount); //reverse edge
  119. }
  120. }
  121. }
  122. }
  123.  
  124. //DFS on parents
  125. barn.barnancestor = true;
  126. barn.distance = 0;
  127. ancestordfs(barn);
  128.  
  129. //Find longest paths to all children
  130.  
  131. ArrayList<Integer> ordered = new ArrayList<Integer>();
  132.  
  133. for (int i = count - 1; i >= 0; i--) {
  134. ordered.add(i);
  135. }
  136.  
  137. dpdown(vertices, ordered);
  138. dpup(vertices, ordered);
  139.  
  140. int answer = barn.pastureCount;
  141. for (int i = 0; i < vertices.length; i++) {
  142. if (!vertices[i].barnancestor) {
  143. for (int j = 0; j < vertices[i].parents.size(); j++) {
  144. if (vertices[i].parents.get(j).barnancestor) {
  145. answer = Math.max(answer, vertices[i].distance + vertices[i].parents.get(j).distance + barn.pastureCount);
  146. }
  147. }
  148. }
  149. }
  150.  
  151. barn.barnancestor = false;
  152. for (int i = 0; i < vertices.length; i++) {
  153. if (!vertices[i].barnancestor) {
  154. for (int j = 0; j < vertices[i].parents.size(); j++) {
  155. if (vertices[i].parents.get(j).barnancestor) {
  156. answer = Math.max(answer, vertices[i].distance + vertices[i].parents.get(j).distance + barn.pastureCount);
  157. }
  158. }
  159. }
  160. }
  161.  
  162. w.println(answer);
  163. w.flush();
  164. }
  165.  
  166. public static void dpdown(Vertex[] vertices, ArrayList<Integer> order) {
  167. for (int i = 0; i < order.size(); i++) {
  168. Vertex current = vertices[order.get(i)];
  169. if (current.barnancestor && current != vertices[id[0]]) continue;
  170.  
  171. for (int j = 0; j < current.adjacents.size(); j++) {
  172. current.adjacents.get(j).distance = Math.max(current.adjacents.get(j).distance, current.distance + current.costs.get(j));
  173. }
  174. }
  175. }
  176.  
  177. public static void dpup(Vertex[] vertices, ArrayList<Integer> order) {
  178. for (int i = order.size() - 1; i >= 0; i--) {
  179. Vertex current = vertices[order.get(i)];
  180. if (!current.barnancestor) continue;
  181.  
  182. for (int j = 0; j < current.parents.size(); j++) {
  183. current.parents.get(j).distance = Math.max(current.parents.get(j).distance, current.distance + current.parentCosts.get(j));
  184. }
  185. }
  186. }
  187.  
  188. public static void ancestordfs(Vertex current) {
  189. for (int i = 0; i < current.parents.size(); i++) {
  190. Vertex parent = current.parents.get(i);
  191. if (!parent.barnancestor) {
  192. parent.barnancestor = true;
  193. ancestordfs(parent);
  194. }
  195. }
  196. }
  197.  
  198. public static class Vertex implements Comparable<Vertex> {
  199. int number;
  200. ArrayList<Vertex> adjacents = new ArrayList<Vertex>();
  201. ArrayList<Integer> costs = new ArrayList<Integer>();
  202. ArrayList<Vertex> parents = new ArrayList<Vertex>();
  203. ArrayList<Integer> parentCosts = new ArrayList<Integer>();
  204. HashSet<Vertex> alreadyAdded = new HashSet<Vertex>();
  205. int distance = infinity;
  206. boolean intree = false;
  207. int to = 0;
  208. Vertex previous;
  209. boolean visited = false;
  210. boolean inQueue = false;
  211. int flow = infinity;
  212. int pastureCount;
  213. boolean barnancestor = false;
  214.  
  215. public Vertex(int n) {
  216. number = n;
  217. }
  218.  
  219. public void addPath(Vertex to, int value) {
  220. adjacents.add(to);
  221. costs.add(value);
  222. alreadyAdded.add(to);
  223. }
  224.  
  225. public void addParent(Vertex p, int value) {
  226. parents.add(p);
  227. parentCosts.add(value);
  228. alreadyAdded.add(p);
  229. }
  230.  
  231. public String toString() {
  232. return number + " " + distance;
  233. }
  234.  
  235. public int compareTo(Vertex v) {
  236. return adjacents.size() - v.adjacents.size();
  237. }
  238.  
  239. public int hashCode() {
  240. return number;
  241. }
  242. }
  243. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement