qwerty787788

minimizing

Nov 20th, 2013
257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.15 KB | None | 0 0
  1. import java.io.*;
  2. import java.util.*;
  3.  
  4. public class AutomatoTask3 {
  5.  
  6.     class R {
  7.         char c;
  8.         int to;
  9.  
  10.         R(char c, int to) {
  11.             this.c = c;
  12.             this.to = to;
  13.         }
  14.     }
  15.  
  16.     class Automato {
  17.         int n, m, k;
  18.         ArrayList<R>[] hm;
  19.         boolean[] end;
  20.  
  21.         Automato() {
  22.             n = in.nextInt();
  23.             m = in.nextInt();
  24.             k = in.nextInt();
  25.             hm = new ArrayList[n];
  26.             end = new boolean[n];
  27.             for (int i = 0; i < k; i++)
  28.                 end[in.nextInt() - 1] = true;
  29.             for (int i = 0; i < n; i++)
  30.                 hm[i] = new ArrayList<>();
  31.             for (int j = 0; j < m; j++) {
  32.                 int fr = in.nextInt() - 1;
  33.                 int to = in.nextInt() - 1;
  34.                 char c = in.next().charAt(0);
  35.                 hm[fr].add(new R(c, to));
  36.             }
  37.         }
  38.  
  39.         void print() {
  40.             out.println(n + " " + m + " " + k);
  41.             for (int i = 0; i < n; i++)
  42.                 if (end[i])
  43.                     out.print((i + 1) + " ");
  44.             out.println();
  45.             for (int i = 0; i < n; i++)
  46.                 for (R entry : hm[i]) {
  47.                     out.println((i + 1) + " " + (entry.to + 1) + " "
  48.                             + entry.c);
  49.                 }
  50.         }
  51.  
  52.         void removeInaccessibleStates() {
  53.             int[] q = new int[n];
  54.             int it = 0, sz = 1;
  55.             boolean[] was = new boolean[n];
  56.             was[0] = true;
  57.             while (it < sz) {
  58.                 int v = q[it++];
  59.                 for (R entry : hm[v]) {
  60.                     if (!was[entry.to]) {
  61.                         q[sz++] = entry.to;
  62.                         was[entry.to] = true;
  63.                     }
  64.                 }
  65.             }
  66.             ArrayList<Integer>[] arrRev = new ArrayList[n];
  67.             for (int i = 0; i < arrRev.length; i++)
  68.                 arrRev[i] = new ArrayList<>();
  69.             for (int i = 0; i < n; i++)
  70.                 for (R entry : hm[i]) {
  71.                     arrRev[entry.to].add(i);
  72.                 }
  73.             boolean[] was2 = new boolean[n];
  74.             for (int i = 0; i < n; i++)
  75.                 if (end[i] && !was2[i]) {
  76.                     was2[i] = true;
  77.                     it = 0;
  78.                     sz = 1;
  79.                     q[0] = i;
  80.                     while (it < sz) {
  81.                         int v = q[it++];
  82.                         for (int j = 0; j < arrRev[v].size(); j++)
  83.                             if (!was2[arrRev[v].get(j)]) {
  84.                                 was2[arrRev[v].get(j)] = true;
  85.                                 q[sz++] = arrRev[v].get(j);
  86.                             }
  87.                     }
  88.                 }
  89.             int[] newId = new int[n];
  90.             Arrays.fill(newId, -1);
  91.             sz = 0;
  92.             for (int i = 0; i < n; i++) {
  93.                 if (was[i] && was2[i])
  94.                     newId[i] = sz++;
  95.             }
  96.             ArrayList<R>[] hm2 = new ArrayList[sz];
  97.             for (int i = 0; i < hm2.length; i++)
  98.                 hm2[i] = new ArrayList<>();
  99.             int m2 = 0;
  100.             for (int i = 0; i < n; i++)
  101.                 if (was[i])
  102.                     for (R entry : hm[i]) {
  103.                         if (newId[entry.to] != -1) {
  104.                             hm2[newId[i]].add(new R(entry.c,
  105.                                     newId[entry.to]));
  106.                             m2++;
  107.                         }
  108.                     }
  109.             m = m2;
  110.             hm = hm2;
  111.             boolean[] end2 = new boolean[sz];
  112.             for (int i = 0; i < n; i++)
  113.                 if (newId[i] != -1)
  114.                     end2[newId[i]] = end[i];
  115.             end = end2;
  116.             n = sz;
  117.             k = 0;
  118.             for (int i = 0; i < n; i++)
  119.                 if (end[i])
  120.                     k++;
  121.         }
  122.     }
  123.    
  124.     long edge(long from, long to, char c) {
  125.         return (from << 40) + (to << 20) + c;
  126.     }
  127.  
  128.     class MyLinkedList {
  129.         Road first, last;
  130.         int size;
  131.  
  132.         MyLinkedList() {
  133.             first = new Road(-1, -1, 'a');
  134.             last = new Road(-1, -1, 'a');
  135.             first.next = last;
  136.             last.prev = first;
  137.             first.list = last.list = this;
  138.         }
  139.  
  140.         void addElement(Road newRoad) {
  141.             Road prevToLast = last.prev;
  142.             prevToLast.next = newRoad;
  143.             last.prev = newRoad;
  144.             size++;
  145.             newRoad.prev = prevToLast;
  146.             newRoad.next = last;
  147.         }
  148.  
  149.     }
  150.  
  151.     class Road {
  152.         int from, to;
  153.         char c;
  154.         Road next, prev;
  155.         MyLinkedList list;
  156.  
  157.         Road(int from, int to, char c) {
  158.             this.from = from;
  159.             this.to = to;
  160.             this.c = c;
  161.         }
  162.  
  163.         void removeThisElementFromList() {
  164.             if (prev == null)
  165.                 return;
  166.             prev.next = next;
  167.             next.prev = prev;
  168.             list.size--;
  169.         }
  170.     }
  171.  
  172.     Automato minimize(Automato a) {
  173.         a.removeInaccessibleStates();
  174.         if (a.n == 0) {
  175.             return a;
  176.         }
  177.         n = a.n;
  178.         int numberOfSets = 0;
  179.         HashMap<Integer, Integer> toSetId = new HashMap<>();
  180.         setId = new int[n];
  181.         for (int i = 0; i < n; i++) {
  182.             int hasRoads = a.end[i] ? 1 : 0;
  183.             for (R entry : a.hm[i]) {
  184.                 hasRoads |= (1 << (entry.c - 'a' + 1));
  185.             }
  186.             Integer x = toSetId.get(hasRoads);
  187.             if (x == null) {
  188.                 x = numberOfSets++;
  189.                 toSetId.put(hasRoads, x);
  190.             }
  191.             setId[i] = x;
  192.         }
  193.         roadsFrom = new ArrayList[n];
  194.         roadsTo = new ArrayList[n];
  195.         for (int i = 0; i < n; i++) {
  196.             roadsFrom[i] = new ArrayList<>();
  197.             roadsTo[i] = new ArrayList<>();
  198.         }
  199.         for (int i = 0; i < n; i++)
  200.             for (R entry : a.hm[i]) {
  201.                 Road r = new Road(i, entry.to, entry.c);
  202.                 roadsFrom[i].add(r);
  203.                 roadsTo[r.to].add(r);
  204.             }
  205.         lists = new ArrayList<>();
  206.         listsArr = new ArrayList<>();
  207.         while (lists.size() < numberOfSets) {
  208.             addNewSet();
  209.         }
  210.         maybeInterestingPairs = new HashSet<>();
  211.         maybeInterestingPairsValsCharacter = new ArrayList<>();
  212.         maybeInterestingPairsValsInteger = new ArrayList<>();
  213.         for (int i = 0; i < n; i++)
  214.             for (int j = 0; j < roadsFrom[i].size(); j++) {
  215.                 Road r = roadsFrom[i].get(j);
  216.                 addRoadToList(r);
  217.             }
  218.         int it = 0;
  219.         while (it < maybeInterestingPairsValsCharacter.size()) {
  220.             char c = maybeInterestingPairsValsCharacter.get(it);
  221.             int id = maybeInterestingPairsValsInteger.get(it);
  222.             if (!isPairInteresting(id, c)) {
  223.                 int val = (id << 5) + (c - 'a');
  224.                 maybeInterestingPairs.remove(val);
  225.                 it++;
  226.             }
  227.         }
  228.         int x = setId[0];
  229.         for (int i = 0; i < n; i++)
  230.             if (setId[i] == 0) {
  231.                 setId[i] = x;
  232.             } else {
  233.                 if (setId[i] == x) {
  234.                     setId[i] = 0;
  235.                 }
  236.             }
  237.         int n2 = lists.size();
  238.         boolean[] end = new boolean[n2];
  239.         for (int i = 0; i < n; i++)
  240.             end[setId[i]] = a.end[i];
  241.         ArrayList<R>[] hm = new ArrayList[n2];
  242.         for (int i = 0; i < n2; i++) {
  243.             hm[i] = new ArrayList<>();
  244.         }
  245.         HashSet<Long> wasHS = new HashSet<Long>();
  246.         for (int i = 0; i < n; i++)
  247.             for (R entry : a.hm[i]) {
  248.                 long e = edge(setId[i], setId[entry.to], entry.c);
  249.                 if (wasHS.contains(e))
  250.                     continue;
  251.                 wasHS.add(e);
  252.                 hm[setId[i]].add(new R(entry.c, setId[entry.to]));
  253.             }
  254.         a.m = 0;
  255.         a.k = 0;
  256.         for (int i = 0; i < n2; i++)
  257.             a.m += hm[i].size();
  258.         for (int i = 0; i < n2; i++)
  259.             a.k += end[i] ? 1 : 0;
  260.         a.end = end;
  261.         a.hm = hm;
  262.         a.n = n2;
  263.         return a;
  264.     }
  265.  
  266.     void addNewSet() {
  267.         HashMap<Integer, MyLinkedList>[] tmp = new HashMap[26];
  268.         ArrayList<PairIntegerLinkedList>[] tmp2 = new ArrayList[26];
  269.         for (int i = 0; i < 26; i++) {
  270.             // tmp[i] = new HashMap<>(0);
  271.             // tmp2[i] = new ArrayList<>(0);
  272.         }
  273.         lists.add(tmp);
  274.         listsArr.add(tmp2);
  275.     }
  276.  
  277.     boolean isPairInteresting(int id, char c) {
  278.         ArrayList<PairIntegerLinkedList> list = listsArr.get(id)[c - 'a'];
  279.         for (int last = 0; last < 2; last++) {
  280.             while (list.size() > last
  281.                     && list.get(list.size() - last - 1).list.size == 0) {
  282.                 lists.get(id)[c - 'a']
  283.                         .remove(list.get(list.size() - last - 1).val);
  284.                 list.remove(list.size() - last - 1);
  285.             }
  286.         }
  287.         if (list.size() <= 1)
  288.             return false;
  289.         MyLinkedList l1 = list.get(list.size() - 1).list;
  290.         MyLinkedList l2 = list.get(list.size() - 2).list;
  291.         ArrayList<Integer> removedElements = new ArrayList<>();
  292.         if (l1.size < l2.size) {
  293.             Road r = l1.first.next;
  294.             while (r != l1.last) {
  295.                 removedElements.add(r.from);
  296.                 r = r.next;
  297.             }
  298.         } else {
  299.             Road r = l2.first.next;
  300.             while (r != l2.last) {
  301.                 removedElements.add(r.from);
  302.                 r = r.next;
  303.             }
  304.         }
  305.         addNewSet();
  306.         for (int i = 0; i < removedElements.size(); i++) {
  307.             int v = removedElements.get(i);
  308.             setId[v] = lists.size() - 1;
  309.         }
  310.         for (int i = 0; i < removedElements.size(); i++) {
  311.             int v = removedElements.get(i);
  312.             for (int j = 0; j < roadsFrom[v].size(); j++) {
  313.                 roadsFrom[v].get(j).removeThisElementFromList();
  314.                 addRoadToList(roadsFrom[v].get(j));
  315.             }
  316.             for (int j = 0; j < roadsTo[v].size(); j++) {
  317.                 roadsTo[v].get(j).removeThisElementFromList();
  318.                 addRoadToList(roadsTo[v].get(j));
  319.             }
  320.         }
  321.         return true;
  322.     }
  323.  
  324.     HashSet<Integer> maybeInterestingPairs;
  325.     ArrayList<Integer> maybeInterestingPairsValsInteger;
  326.     ArrayList<Character> maybeInterestingPairsValsCharacter;
  327.  
  328.     void addMaybeInterestingPair(int from, char c) {
  329.         int val = (from << 5) + (c - 'a');
  330.         if (maybeInterestingPairs.contains(val))
  331.             return;
  332.         maybeInterestingPairs.add(val);
  333.         maybeInterestingPairsValsCharacter.add(c);
  334.         maybeInterestingPairsValsInteger.add(from);
  335.     }
  336.  
  337.     void check(int id, char c) {
  338.         if (lists.get(id)[c - 'a'] == null)
  339.             lists.get(id)[c - 'a'] = new HashMap<Integer, AutomatoTask3.MyLinkedList>(
  340.                     0);
  341.         if (listsArr.get(id)[c - 'a'] == null)
  342.             listsArr.get(id)[c - 'a'] = new ArrayList<>();
  343.     }
  344.  
  345.     MyLinkedList getList(int setId, char c, int to) {
  346.         check(setId, c);
  347.         MyLinkedList result = lists.get(setId)[c - 'a'].get(to);
  348.         if (result == null) {
  349.             result = new MyLinkedList();
  350.             lists.get(setId)[c - 'a'].put(to, result);
  351.             PairIntegerLinkedList pair = new PairIntegerLinkedList(to, result);
  352.             listsArr.get(setId)[c - 'a'].add(pair);
  353.         }
  354.         return result;
  355.     }
  356.  
  357.     void addRoadToList(Road r) {
  358.         MyLinkedList list = getList(setId[r.from], r.c, setId[r.to]);
  359.         list.addElement(r);
  360.         r.list = list;
  361.         addMaybeInterestingPair(setId[r.from], r.c);
  362.     }
  363.  
  364.     int n;
  365.     int[] setId;
  366.     ArrayList<Road>[] roadsFrom;
  367.     ArrayList<Road>[] roadsTo;
  368.     ArrayList<HashMap<Integer, MyLinkedList>[]> lists;
  369.     ArrayList<ArrayList<PairIntegerLinkedList>[]> listsArr;
  370.  
  371.     class PairIntegerLinkedList {
  372.         int val;
  373.         MyLinkedList list;
  374.  
  375.         public PairIntegerLinkedList(int val, MyLinkedList list) {
  376.             super();
  377.             this.val = val;
  378.             this.list = list;
  379.         }
  380.  
  381.     }
  382.  
  383.     void solve() {
  384. //      long st = System.currentTimeMillis();
  385.         Automato a1 = new Automato();
  386.         // Automato a2 = new Automato();
  387.         // if (same(a1, a2)) {
  388.         // out.println("YES");
  389.         // } else {
  390.         // out.println("NO");
  391.         // }
  392.         a1 = minimize(a1);
  393.         a1.print();
  394. //      System.err.println(System.currentTimeMillis() - st);
  395.     }
  396.  
  397.     InputReader in;
  398.     PrintWriter out;
  399.  
  400.     void runIO() {
  401.         in = new InputReader(System.in);
  402.         out = new PrintWriter(System.out);
  403.  
  404.         solve();
  405.  
  406.         out.close();
  407.     }
  408.  
  409.     void run() {
  410.         in = new InputReader(new File("fastminimization.in"));
  411.         try {
  412.             out = new PrintWriter(new File("fastminimization.out"));
  413.         } catch (FileNotFoundException e) {
  414.             e.printStackTrace();
  415.         }
  416.  
  417.         solve();
  418.  
  419.         out.close();
  420.     }
  421.  
  422.     public static void main(String[] args) {
  423.         new AutomatoTask3().run();
  424.     }
  425.  
  426.     class InputReader {
  427.         BufferedReader bf;
  428.         StringTokenizer st;
  429.  
  430.         InputReader(File f) {
  431.             try {
  432.                 bf = new BufferedReader(new FileReader(f));
  433.             } catch (FileNotFoundException e) {
  434.                 e.printStackTrace();
  435.             }
  436.         }
  437.  
  438.         InputReader(InputStream s) {
  439.             bf = new BufferedReader(new InputStreamReader(s));
  440.         }
  441.  
  442.         String next() {
  443.             while (st == null || !st.hasMoreElements()) {
  444.                 String s;
  445.                 try {
  446.                     s = bf.readLine();
  447.                 } catch (IOException e) {
  448.                     return null;
  449.                 }
  450.                 if (s == null)
  451.                     return null;
  452.                 st = new StringTokenizer(s);
  453.             }
  454.             return st.nextToken();
  455.         }
  456.  
  457.         int nextInt() {
  458.             return Integer.parseInt(next());
  459.         }
  460.  
  461.         long nextLong() {
  462.             return Long.parseLong(next());
  463.         }
  464.  
  465.         double nextDouble() {
  466.             return Double.parseDouble(next());
  467.         }
  468.  
  469.         boolean hasMoreElements() {
  470.             while (!st.hasMoreElements()) {
  471.                 String s;
  472.                 try {
  473.                     s = bf.readLine();
  474.                 } catch (IOException e) {
  475.                     return false;
  476.                 }
  477.                 if (s == null)
  478.                     return false;
  479.                 st = new StringTokenizer(s);
  480.             }
  481.             return true;
  482.         }
  483.     }
  484. }
Advertisement
Add Comment
Please, Sign In to add comment