#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; } |
English