#include <stdio.h> #include <algorithm> #include <set> #include <vector> using namespace std; struct step_t { int from, to; }; struct reaction_t { int s1, s2, priority; }; struct CompareReactionsPrior { bool operator()(const reaction_t &lhs, const reaction_t &rhs) const { return lhs.priority < rhs.priority; } }; struct CompareReactionsSubst { bool operator()(const reaction_t &lhs, const reaction_t &rhs) const { return lhs.s1 == rhs.s1? lhs.s2 < rhs.s2 : lhs.s1 < rhs.s1; } }; int main() { int n, m, k; scanf("%d %d %d", &n, &m, &k); int *subs = new int[n]; set<int> *flasks = new set<int>[n]; for(int i = 0; i < n; ++i) { scanf("%d", &subs[i]); flasks[i].insert(i); } step_t *steps = new step_t[m]; for(int i = 0; i < m; ++i) { scanf("%d %d", &steps[i].from, &steps[i].to); --steps[i].from; --steps[i].to; } set<reaction_t, CompareReactionsPrior> reactionsPrior; set<reaction_t, CompareReactionsSubst> reactionsSubst; for(int i = 0; i < k; ++i) { reaction_t r; scanf("%d %d", &r.s1, &r.s2); --r.s1; --r.s2; r.priority = i; if(r.s1 > r.s2) swap(r.s1, r.s2); reactionsPrior.insert(r); reactionsSubst.insert(r); } long long result = 0; for(int i = 0; i < m; ++i) { int from = steps[i].from, to = steps[i].to; vector<reaction_t> thisReactions; //fprintf(stderr, "Step %d: merging %d and %d\n", i, from, to); //fprintf(stderr, "Product: %d, reactions: %d\n", flasks[from].size() * flasks[to].size(), reactionsPrior.size()); if(flasks[from].size() * flasks[to].size() > reactionsPrior.size()) { //fprintf(stderr, "Checking all reactions\n"); for(set<reaction_t, CompareReactionsPrior>::iterator it = reactionsPrior.begin(); it != reactionsPrior.end(); ++it) if((flasks[from].find(it->s1) != flasks[from].end() && flasks[to].find(it->s2) != flasks[to].end()) || (flasks[from].find(it->s2) != flasks[from].end() && flasks[to].find(it->s1) != flasks[to].end())) thisReactions.push_back(*it); } else { //fprintf(stderr, "Checking all pairs of substances\n"); for(set<int>::iterator it1 = flasks[from].begin(); it1 != flasks[from].end(); ++it1) { for(set<int>::iterator it2 = flasks[to].begin(); it2 != flasks[to].end(); ++it2) { reaction_t lookup = { s1: min(*it1, *it2), s2: max(*it1, *it2), }; set<reaction_t, CompareReactionsSubst>::iterator result = reactionsSubst.find(lookup); if(result != reactionsSubst.end()) thisReactions.push_back(*result); } } sort(thisReactions.begin(), thisReactions.end(), CompareReactionsPrior()); } //fprintf(stderr, "Found %d reactions\n", thisReactions.size()); for(vector<reaction_t>::iterator it = thisReactions.begin(); it != thisReactions.end(); ++it) { int common = min(subs[it->s1], subs[it->s2]); result += 2 * common; subs[it->s1] -= common; subs[it->s2] -= common; if(flasks[from].find(it->s1) != flasks[from].end() && flasks[to].find(it->s2) != flasks[to].end()) { if(subs[it->s1] == 0) flasks[from].erase(it->s1); if(subs[it->s2] == 0) flasks[to].erase(it->s2); } else if(flasks[from].find(it->s2) != flasks[from].end() && flasks[to].find(it->s1) != flasks[to].end()) { if(subs[it->s1] == 0) flasks[to].erase(it->s1); if(subs[it->s2] == 0) flasks[from].erase(it->s2); } } if(flasks[from].size() > flasks[to].size()) { flasks[from].insert(flasks[to].begin(), flasks[to].end()); flasks[from].swap(flasks[to]); } else flasks[to].insert(flasks[from].begin(), flasks[from].end()); flasks[from].clear(); for(vector<reaction_t>::iterator it = thisReactions.begin(); it != thisReactions.end(); ++it) { reactionsPrior.erase(*it); reactionsSubst.erase(*it); } } printf("%lld\n", result); return 0; }
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 | #include <stdio.h> #include <algorithm> #include <set> #include <vector> using namespace std; struct step_t { int from, to; }; struct reaction_t { int s1, s2, priority; }; struct CompareReactionsPrior { bool operator()(const reaction_t &lhs, const reaction_t &rhs) const { return lhs.priority < rhs.priority; } }; struct CompareReactionsSubst { bool operator()(const reaction_t &lhs, const reaction_t &rhs) const { return lhs.s1 == rhs.s1? lhs.s2 < rhs.s2 : lhs.s1 < rhs.s1; } }; int main() { int n, m, k; scanf("%d %d %d", &n, &m, &k); int *subs = new int[n]; set<int> *flasks = new set<int>[n]; for(int i = 0; i < n; ++i) { scanf("%d", &subs[i]); flasks[i].insert(i); } step_t *steps = new step_t[m]; for(int i = 0; i < m; ++i) { scanf("%d %d", &steps[i].from, &steps[i].to); --steps[i].from; --steps[i].to; } set<reaction_t, CompareReactionsPrior> reactionsPrior; set<reaction_t, CompareReactionsSubst> reactionsSubst; for(int i = 0; i < k; ++i) { reaction_t r; scanf("%d %d", &r.s1, &r.s2); --r.s1; --r.s2; r.priority = i; if(r.s1 > r.s2) swap(r.s1, r.s2); reactionsPrior.insert(r); reactionsSubst.insert(r); } long long result = 0; for(int i = 0; i < m; ++i) { int from = steps[i].from, to = steps[i].to; vector<reaction_t> thisReactions; //fprintf(stderr, "Step %d: merging %d and %d\n", i, from, to); //fprintf(stderr, "Product: %d, reactions: %d\n", flasks[from].size() * flasks[to].size(), reactionsPrior.size()); if(flasks[from].size() * flasks[to].size() > reactionsPrior.size()) { //fprintf(stderr, "Checking all reactions\n"); for(set<reaction_t, CompareReactionsPrior>::iterator it = reactionsPrior.begin(); it != reactionsPrior.end(); ++it) if((flasks[from].find(it->s1) != flasks[from].end() && flasks[to].find(it->s2) != flasks[to].end()) || (flasks[from].find(it->s2) != flasks[from].end() && flasks[to].find(it->s1) != flasks[to].end())) thisReactions.push_back(*it); } else { //fprintf(stderr, "Checking all pairs of substances\n"); for(set<int>::iterator it1 = flasks[from].begin(); it1 != flasks[from].end(); ++it1) { for(set<int>::iterator it2 = flasks[to].begin(); it2 != flasks[to].end(); ++it2) { reaction_t lookup = { s1: min(*it1, *it2), s2: max(*it1, *it2), }; set<reaction_t, CompareReactionsSubst>::iterator result = reactionsSubst.find(lookup); if(result != reactionsSubst.end()) thisReactions.push_back(*result); } } sort(thisReactions.begin(), thisReactions.end(), CompareReactionsPrior()); } //fprintf(stderr, "Found %d reactions\n", thisReactions.size()); for(vector<reaction_t>::iterator it = thisReactions.begin(); it != thisReactions.end(); ++it) { int common = min(subs[it->s1], subs[it->s2]); result += 2 * common; subs[it->s1] -= common; subs[it->s2] -= common; if(flasks[from].find(it->s1) != flasks[from].end() && flasks[to].find(it->s2) != flasks[to].end()) { if(subs[it->s1] == 0) flasks[from].erase(it->s1); if(subs[it->s2] == 0) flasks[to].erase(it->s2); } else if(flasks[from].find(it->s2) != flasks[from].end() && flasks[to].find(it->s1) != flasks[to].end()) { if(subs[it->s1] == 0) flasks[to].erase(it->s1); if(subs[it->s2] == 0) flasks[from].erase(it->s2); } } if(flasks[from].size() > flasks[to].size()) { flasks[from].insert(flasks[to].begin(), flasks[to].end()); flasks[from].swap(flasks[to]); } else flasks[to].insert(flasks[from].begin(), flasks[from].end()); flasks[from].clear(); for(vector<reaction_t>::iterator it = thisReactions.begin(); it != thisReactions.end(); ++it) { reactionsPrior.erase(*it); reactionsSubst.erase(*it); } } printf("%lld\n", result); return 0; } |