qwerty787788

Graph / Tree / Bridges

Jun 21st, 2020
1,386
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 10.51 KB | None | 0 0
  1. import java.util.*;
  2. import java.math.*;
  3.  
  4. import static java.lang.Math.*;
  5.  
  6. public class AqaAsadiSaves {
  7.  
  8.     class Edge {
  9.         int to, id;
  10.  
  11.         public Edge(int to, int id) {
  12.             this.to = to;
  13.             this.id = id;
  14.         }
  15.  
  16.     }
  17.  
  18.     class SuperVertex {
  19.         List<Integer> insideVertices;
  20.  
  21.         SuperVertex() {
  22.             insideVertices = new ArrayList<>();
  23.         }
  24.  
  25.         public void add(int v) {
  26.             insideVertices.add(v);
  27.         }
  28.  
  29.         @Override
  30.         public String toString() {
  31.             return "SuperVertex{" +
  32.                     "insideVertices=" + insideVertices +
  33.                     '}';
  34.         }
  35.     }
  36.  
  37.     class Dsu {
  38.         int[] p;
  39.  
  40.         int get(int x) {
  41.             return p[x] == x ? x : (p[x] = get(p[x]));
  42.         }
  43.  
  44.         void unite(int x, int y) {
  45.             p[get(x)] = get(y);
  46.         }
  47.  
  48.         Dsu(int n) {
  49.             p = new int[n];
  50.             for (int i = 0; i < n; i++) {
  51.                 p[i] = i;
  52.             }
  53.         }
  54.     }
  55.  
  56.     class TreeForest {
  57.         List<Integer>[] g;
  58.         int[] rootIds;
  59.         int n;
  60.         int time;
  61.         int[] tin, tout;
  62.         int layers;
  63.         int[][] up;
  64.  
  65.         TreeForest(int n) {
  66.             this.n = n;
  67.             g = new List[n];
  68.             for (int i = 0; i < n; i++) {
  69.                 g[i] = new ArrayList<>();
  70.             }
  71.             tin = new int[n];
  72.             tout = new int[n];
  73.         }
  74.  
  75.         void addEdge(int fr, int to) {
  76.             g[fr].add(to);
  77.             g[to].add(fr);
  78.         }
  79.  
  80.         void dfs(int v, int rootId, int p) {
  81.             up[0][v] = p;
  82.             for (int i = 1; i < up.length; i++) {
  83.                 up[i][v] = up[i - 1][up[i - 1][v]];
  84.             }
  85.             tin[v] = time++;
  86.             rootIds[v] = rootId;
  87.             for (int to : g[v]) {
  88.                 if (to == p) {
  89.                     continue;
  90.                 }
  91.                 dfs(to, rootId, v);
  92.             }
  93.             tout[v] = time;
  94.         }
  95.  
  96.         boolean isInside(int parent, int ch) {
  97.             return tin[ch] >= tin[parent] && tout[ch] <= tout[parent];
  98.         }
  99.  
  100.         int lca(int x, int y) {
  101.             for (int i = layers - 1; i >= 0; i--) {
  102.                 if (!isInside(up[i][x], y)) {
  103.                     x = up[i][x];
  104.                 }
  105.             }
  106.             if (isInside(x, y)) {
  107.                 return x;
  108.             }
  109.             return up[0][x];
  110.         }
  111.  
  112.         boolean isOnPath(int from, int to, int what) {
  113.             int lca = lca(from, to);
  114.             if (!isInside(lca, what)) {
  115.                 return false;
  116.             }
  117.             return isInside(what, from) || isInside(what, to);
  118.         }
  119.  
  120.         void build() {
  121.             // TODO: change 2?
  122.             layers = Integer.numberOfTrailingZeros(Integer.highestOneBit(n)) + 2;
  123.             up = new int[layers][n];
  124.             rootIds = new int[n];
  125.             Arrays.fill(rootIds, -1);
  126.             for (int i = 0; i < n; i++) {
  127.                 if (rootIds[i] != -1) {
  128.                     continue;
  129.                 }
  130.                 dfs(i, i, i);
  131.             }
  132.         }
  133.     }
  134.  
  135.     class TwoConnectedComponents {
  136.         SuperVertex[] vertices;
  137.         List<Integer>[] graph;
  138.  
  139.         public TwoConnectedComponents(SuperVertex[] vertices, List<Integer>[] graph) {
  140.             this.vertices = vertices;
  141.             this.graph = graph;
  142.         }
  143.  
  144.         @Override
  145.         public String toString() {
  146.             return "TwoConnectedComponents{" +
  147.                     "vertices=" + Arrays.toString(vertices) +
  148.                     ", graph=" + Arrays.toString(graph) +
  149.                     '}';
  150.         }
  151.     }
  152.  
  153.     class Graph {
  154.         int n;
  155.         List<Edge>[] g;
  156.         int totEdges;
  157.         int[] tin, fup;
  158.         int timer;
  159.  
  160.  
  161.         Graph(int n) {
  162.             this.n = n;
  163.             g = new List[n];
  164.             for (int i = 0; i < n; i++) {
  165.                 g[i] = new ArrayList<>();
  166.             }
  167.         }
  168.  
  169.         void addEdge(int fr, int to) {
  170.             Edge e1 = new Edge(to, totEdges);
  171.             Edge e2 = new Edge(fr, totEdges);
  172.             g[fr].add(e1);
  173.             g[to].add(e2);
  174.             totEdges++;
  175.         }
  176.  
  177.         void dfs(int v, int pEdgeId, boolean[] was, boolean[] isBridge) {
  178.             was[v] = true;
  179.             tin[v] = fup[v] = timer++;
  180.             for (int i = 0; i < g[v].size(); i++) {
  181.                 Edge e = g[v].get(i);
  182.                 if (e.id == pEdgeId) {
  183.                     continue;
  184.                 }
  185.                 if (was[e.to]) {
  186.                     fup[v] = Math.min(fup[v], tin[e.to]);
  187.                 } else {
  188.                     dfs(e.to, e.id, was, isBridge);
  189.                     fup[v] = Math.min(fup[v], fup[e.to]);
  190.                     if (fup[e.to] > tin[v]) {
  191.                         isBridge[e.id] = true;
  192.                     }
  193.                 }
  194.             }
  195.         }
  196.  
  197.         TwoConnectedComponents findTwoConnectedComponents() {
  198.             boolean[] isBridge = new boolean[totEdges];
  199.             boolean[] was = new boolean[n];
  200.             tin = new int[n];
  201.             fup = new int[n];
  202.             for (int v = 0; v < n; v++) {
  203.                 if (was[v]) {
  204.                     continue;
  205.                 }
  206.                 dfs(v, -1, was, isBridge);
  207.             }
  208.             Dsu dsu = new Dsu(n);
  209.             for (int i = 0; i < n; i++) {
  210.                 for (Edge e : g[i]) {
  211.                     if (isBridge[e.id]) {
  212.                         continue;
  213.                     }
  214.                     dsu.unite(i, e.to);
  215.                 }
  216.             }
  217.             int[] newId = new int[n];
  218.             Arrays.fill(newId, -1);
  219.             int nSz = 0;
  220.             for (int i = 0; i < n; i++) {
  221.                 int p = dsu.get(i);
  222.                 if (newId[p] == -1) {
  223.                     newId[p] = nSz++;
  224.                 }
  225.                 newId[i] = newId[p];
  226.             }
  227.             SuperVertex[] vertices = new SuperVertex[nSz];
  228.             for (int i = 0; i < vertices.length; i++) {
  229.                 vertices[i] = new SuperVertex();
  230.             }
  231.             for (int i = 0; i < n; i++) {
  232.                 vertices[newId[i]].add(i);
  233.             }
  234.             List<Integer>[] newGraph = new List[nSz];
  235.             for (int i = 0; i < newGraph.length; i++) {
  236.                 newGraph[i] = new ArrayList<>();
  237.             }
  238.             for (int i = 0; i < n; i++) {
  239.                 for (Edge e : g[i]) {
  240.                     if (isBridge[e.id]) {
  241.                         newGraph[newId[i]].add(newId[e.to]);
  242.                     }
  243.                 }
  244.             }
  245.             return new TwoConnectedComponents(vertices, newGraph);
  246.         }
  247.     }
  248.  
  249.     class WeightedEdge implements Comparable<WeightedEdge> {
  250.         int fr, to;
  251.         long cost;
  252.  
  253.         public WeightedEdge(int fr, int to, long cost) {
  254.             this.fr = fr;
  255.             this.to = to;
  256.             this.cost = cost;
  257.         }
  258.  
  259.         @Override
  260.         public int compareTo(WeightedEdge o) {
  261.             return -Long.compare(cost, o.cost);
  262.         }
  263.  
  264.         @Override
  265.         public String toString() {
  266.             return "WeightedEdge{" +
  267.                     "fr=" + fr +
  268.                     ", to=" + to +
  269.                     ", cost=" + cost +
  270.                     '}';
  271.         }
  272.     }
  273.  
  274.     int findWeightedEdges(TreeForest treeForest, List<WeightedEdge> edges, int v, int p, TwoConnectedComponents twoConnectedComponents) {
  275.         int sz = twoConnectedComponents.vertices[v].insideVertices.size();
  276.         for (int to : treeForest.g[v]) {
  277.             if (to == p) {
  278.                 continue;
  279.             }
  280.             int chSz = findWeightedEdges(treeForest, edges, to, v, twoConnectedComponents);
  281.             edges.add(new WeightedEdge(v, to, chSz));
  282.             sz += chSz;
  283.         }
  284.         return sz;
  285.     }
  286.  
  287.     void addToPath(int[] path, int v, TreeForest treeForest) {
  288.         if (path[0] == -1) {
  289.             return;
  290.         }
  291.         if (treeForest.isOnPath(path[0], path[1], v)) {
  292.             return;
  293.         }
  294.         if (treeForest.isOnPath(path[0], v, path[1])) {
  295.             path[1] = v;
  296.             return;
  297.         }
  298.         if (treeForest.isOnPath(v, path[1], path[0])) {
  299.             path[0] = v;
  300.             return;
  301.         }
  302.         path[0] = path[1] = -1;
  303.     }
  304.  
  305.     public long minDamage(int N, int M, int[] PA, int[] PB, int Seed, int X, int Y) {
  306.         int[] a = new int[M];
  307.         int[] b = new int[M];
  308.         for (int i = 0; i < M; i++) {
  309.             if (i < PA.length) {
  310.                 a[i] = PA[i];
  311.             } else {
  312.                 a[i] = Seed;
  313.                 Seed = (int) ((Seed * 1L * X + Y) % N);
  314.             }
  315.         }
  316.         for (int i = 0; i < M; i++) {
  317.             if (i < PB.length) {
  318.                 b[i] = PB[i];
  319.             } else {
  320.                 b[i] = Seed;
  321.                 Seed = (int) ((Seed * 1L * X + Y) % N);
  322.             }
  323.         }
  324.         Graph graph = new Graph(N);
  325.         for (int i = 0; i < M; i++) {
  326.             graph.addEdge(a[i], b[i]);
  327.         }
  328.         TwoConnectedComponents twoConnectedComponents = graph.findTwoConnectedComponents();
  329.         int nSz = twoConnectedComponents.graph.length;
  330.         TreeForest treeForest = new TreeForest(nSz);
  331.         for (int v = 0; v < nSz; v++) {
  332.             for (int to : twoConnectedComponents.graph[v]) {
  333.                 if (to < v) {
  334.                     continue;
  335.                 }
  336.                 treeForest.addEdge(v, to);
  337.             }
  338.         }
  339.         treeForest.build();
  340.         List<WeightedEdge> allEdges = new ArrayList<>();
  341.         for (int v = 0; v < nSz; v++) {
  342.             if (treeForest.rootIds[v] != v) {
  343.                 continue;
  344.             }
  345.             List<WeightedEdge> edges = new ArrayList<>();
  346.             int curSize = findWeightedEdges(treeForest, edges, v, v, twoConnectedComponents);
  347.             for (WeightedEdge e : edges) {
  348.                 e.cost *= curSize - e.cost;
  349.             }
  350.             allEdges.addAll(edges);
  351.         }
  352.         Collections.sort(allEdges);
  353.         int[] path = new int[]{-1, -1};
  354.         for (WeightedEdge e : allEdges) {
  355.             if (path[0] == -1) {
  356.                 path = new int[]{e.fr, e.to};
  357.             } else {
  358.                 addToPath(path, e.fr, treeForest);
  359.                 addToPath(path, e.to, treeForest);
  360.             }
  361.             if (path[0] == -1) {
  362.                 return e.cost;
  363.             }
  364.         }
  365.         return 0;
  366.     }
  367. }
Advertisement
Add Comment
Please, Sign In to add comment