import java.util.*; public class fio { static final Comparator<Rule> ruleComparator = new Comparator<Rule>() { @Override public int compare(Rule o1, Rule o2) { return o1.idx - o2.idx; } }; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(), m = sc.nextInt(), k = sc.nextInt(); Substance[] substances = new Substance[n + 1]; for (int i = 1; i <= n; i++) { int quantity = sc.nextInt(); substances[i] = new Substance(i, quantity); } int[] from = new int[m + 1]; int[] to = new int[m + 1]; for (int i = 1; i <= m; i++) { from[i] = sc.nextInt() ; to[i] = sc.nextInt(); } int reagentA, reagentB; int reactingRulesIdx = 0; Rule[] reactingRules = new Rule[n + 1]; HashMap<Rule, Rule> hashedRules = new HashMap<Rule, Rule>(); HashMap<Integer, Set<Integer>> reactionRules = new HashMap<Integer, Set<Integer>>(); for (int i = 1; i <= k; i++) { reagentA = sc.nextInt(); reagentB = sc.nextInt(); if (reactionRules.containsKey(reagentA)) { reactionRules.get(reagentA).add(reagentB); } else { Set<Integer> set = new HashSet<Integer>(); set.add(reagentB); reactionRules.put(reagentA, set); } if (reactionRules.containsKey(reagentB)) { reactionRules.get(reagentB).add(reagentA); } else { Set<Integer> set = new HashSet<Integer>(); set.add(reagentA); reactionRules.put(reagentB, set); } Rule rule = new Rule(reagentA, reagentB, i); hashedRules.put(rule, rule); } long totalRest = 0; Set<Substance>[] mixtures = new Set[n + 1]; for (int i = 1; i <= m; ++i) { int sourceIdx = from[i]; int destinationIdx = to[i]; Set<Substance> source = mixtures[sourceIdx]; Set<Substance> destination = mixtures[destinationIdx]; if (source == null) { source = mixtures[sourceIdx] = new HashSet<Substance>(); source.add(substances[sourceIdx]); } // Empty bottle or not-reacting destination if (destination == null && substances[destinationIdx].isUsed) { mixtures[destinationIdx] = source; //mixtures[sourceIdx].clear(); mixtures[sourceIdx] = null; substances[sourceIdx].isUsed = true; continue; } if (destination == null) { destination = mixtures[destinationIdx] = new HashSet<Substance>(); destination.add(substances[destinationIdx]); } for (Substance ss : source) { Set<Integer> reactors = reactionRules.get(ss.idx); if (reactors != null) { for (Substance sd : destination) { if (reactors.contains(sd.idx)) { //reacting.add(hashedRules.get(toRule(ss.idx, sd.idx))); // Optimizing memory reactingRules[reactingRulesIdx++] = hashedRules.get(toRule(ss.idx, sd.idx)); //reactors.remove(sd.idx); //reactionRules.get(sd.idx).remove(ss.idx); } } } } if (reactingRulesIdx > 0) { Arrays.sort(reactingRules, 0, reactingRulesIdx, ruleComparator); for (int j = 0; j < reactingRulesIdx; ++j) { Rule rule = reactingRules[j]; Substance sourceReact = substances[rule.a], destinationReact = substances[rule.b]; if (sourceReact.quantity == destinationReact.quantity) { totalRest += (sourceReact.quantity * 2); sourceReact.quantity = 0; destinationReact.quantity = 0; } else if (sourceReact.quantity > destinationReact.quantity) { totalRest += (destinationReact.quantity * 2); sourceReact.quantity -= destinationReact.quantity; destinationReact.quantity = 0; } else { totalRest += (sourceReact.quantity * 2); destinationReact.quantity -= sourceReact.quantity; sourceReact.quantity = 0; } } reactingRulesIdx = 0; } Set<Substance> newSubstances = new HashSet<Substance>(); for (Substance s : source) { if (s.quantity > 0) { newSubstances.add(s); } } for (Substance s : destination) { if (s.quantity > 0) { newSubstances.add(s); } } mixtures[destinationIdx] = newSubstances; substances[sourceIdx].isUsed = true; mixtures[sourceIdx] = null; } System.out.println(totalRest); } private static final Rule fakeRule = new Rule(0,1,2); public static Rule toRule(int a, int b) { if (a < b) { fakeRule.a = a; fakeRule.b = b; } else { fakeRule.a = b; fakeRule.b = a; } return fakeRule; } } class Substance { int idx; int quantity; boolean isUsed; Substance(int idx, int quantity) { this.idx = idx; this.quantity = quantity; } @Override public boolean equals(Object o) { return idx == ((Substance)o).idx; } @Override public int hashCode() { return idx; } } class Rule { int a; int b; int idx; Rule(int a, int b, int idx) { if (a < b) { this.a = a; this.b = b; } else { this.a = b; this.b = a; } this.idx = idx; } @Override public boolean equals(Object obj) { Rule o = (Rule) obj; return a == o.a && b == o.b; } @Override public int hashCode() { return 31 * a + b; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | import java.util.*; public class fio { static final Comparator<Rule> ruleComparator = new Comparator<Rule>() { @Override public int compare(Rule o1, Rule o2) { return o1.idx - o2.idx; } }; public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(), m = sc.nextInt(), k = sc.nextInt(); Substance[] substances = new Substance[n + 1]; for (int i = 1; i <= n; i++) { int quantity = sc.nextInt(); substances[i] = new Substance(i, quantity); } int[] from = new int[m + 1]; int[] to = new int[m + 1]; for (int i = 1; i <= m; i++) { from[i] = sc.nextInt() ; to[i] = sc.nextInt(); } int reagentA, reagentB; int reactingRulesIdx = 0; Rule[] reactingRules = new Rule[n + 1]; HashMap<Rule, Rule> hashedRules = new HashMap<Rule, Rule>(); HashMap<Integer, Set<Integer>> reactionRules = new HashMap<Integer, Set<Integer>>(); for (int i = 1; i <= k; i++) { reagentA = sc.nextInt(); reagentB = sc.nextInt(); if (reactionRules.containsKey(reagentA)) { reactionRules.get(reagentA).add(reagentB); } else { Set<Integer> set = new HashSet<Integer>(); set.add(reagentB); reactionRules.put(reagentA, set); } if (reactionRules.containsKey(reagentB)) { reactionRules.get(reagentB).add(reagentA); } else { Set<Integer> set = new HashSet<Integer>(); set.add(reagentA); reactionRules.put(reagentB, set); } Rule rule = new Rule(reagentA, reagentB, i); hashedRules.put(rule, rule); } long totalRest = 0; Set<Substance>[] mixtures = new Set[n + 1]; for (int i = 1; i <= m; ++i) { int sourceIdx = from[i]; int destinationIdx = to[i]; Set<Substance> source = mixtures[sourceIdx]; Set<Substance> destination = mixtures[destinationIdx]; if (source == null) { source = mixtures[sourceIdx] = new HashSet<Substance>(); source.add(substances[sourceIdx]); } // Empty bottle or not-reacting destination if (destination == null && substances[destinationIdx].isUsed) { mixtures[destinationIdx] = source; //mixtures[sourceIdx].clear(); mixtures[sourceIdx] = null; substances[sourceIdx].isUsed = true; continue; } if (destination == null) { destination = mixtures[destinationIdx] = new HashSet<Substance>(); destination.add(substances[destinationIdx]); } for (Substance ss : source) { Set<Integer> reactors = reactionRules.get(ss.idx); if (reactors != null) { for (Substance sd : destination) { if (reactors.contains(sd.idx)) { //reacting.add(hashedRules.get(toRule(ss.idx, sd.idx))); // Optimizing memory reactingRules[reactingRulesIdx++] = hashedRules.get(toRule(ss.idx, sd.idx)); //reactors.remove(sd.idx); //reactionRules.get(sd.idx).remove(ss.idx); } } } } if (reactingRulesIdx > 0) { Arrays.sort(reactingRules, 0, reactingRulesIdx, ruleComparator); for (int j = 0; j < reactingRulesIdx; ++j) { Rule rule = reactingRules[j]; Substance sourceReact = substances[rule.a], destinationReact = substances[rule.b]; if (sourceReact.quantity == destinationReact.quantity) { totalRest += (sourceReact.quantity * 2); sourceReact.quantity = 0; destinationReact.quantity = 0; } else if (sourceReact.quantity > destinationReact.quantity) { totalRest += (destinationReact.quantity * 2); sourceReact.quantity -= destinationReact.quantity; destinationReact.quantity = 0; } else { totalRest += (sourceReact.quantity * 2); destinationReact.quantity -= sourceReact.quantity; sourceReact.quantity = 0; } } reactingRulesIdx = 0; } Set<Substance> newSubstances = new HashSet<Substance>(); for (Substance s : source) { if (s.quantity > 0) { newSubstances.add(s); } } for (Substance s : destination) { if (s.quantity > 0) { newSubstances.add(s); } } mixtures[destinationIdx] = newSubstances; substances[sourceIdx].isUsed = true; mixtures[sourceIdx] = null; } System.out.println(totalRest); } private static final Rule fakeRule = new Rule(0,1,2); public static Rule toRule(int a, int b) { if (a < b) { fakeRule.a = a; fakeRule.b = b; } else { fakeRule.a = b; fakeRule.b = a; } return fakeRule; } } class Substance { int idx; int quantity; boolean isUsed; Substance(int idx, int quantity) { this.idx = idx; this.quantity = quantity; } @Override public boolean equals(Object o) { return idx == ((Substance)o).idx; } @Override public int hashCode() { return idx; } } class Rule { int a; int b; int idx; Rule(int a, int b, int idx) { if (a < b) { this.a = a; this.b = b; } else { this.a = b; this.b = a; } this.idx = idx; } @Override public boolean equals(Object obj) { Rule o = (Rule) obj; return a == o.a && b == o.b; } @Override public int hashCode() { return 31 * a + b; } } |