#include <cstdio> #include <vector> #include <algorithm> #include <set> using namespace std; long long result = 0LL; std::vector<int> substanceWeights; struct Triple { Triple(int first_, int second_, int thrid_) : first(first_), second(second_), thrid(thrid_) { } int first, second, thrid; bool operator <(Triple p) const { return first < p.first; } }; template <typename SetType> struct ListJoinSets { ListJoinSets(int n, vector<set<SetType> >& sets) : parents_(n), sets_(sets) { for (int i = 0 ; i < n ; i++) parents_[i] = i; } void join(int from, int to) { //assert(parents_[from] == from); parents_[from] = to; int smallerSet = sets_[from].size() < sets_[to].size() ? from : to; int biggerSet = sets_[from].size() >= sets_[to].size() ? from : to; for (typename set<SetType>::iterator it = sets_[smallerSet].begin() ; it != sets_[smallerSet].end() ; ++it) { if (findAncestor(it->second) == to) { int weight = min(substanceWeights[it->second], substanceWeights[it->thrid]); result += 2 * weight; substanceWeights[it->second] -= weight; substanceWeights[it->thrid] -= weight; } else sets_[biggerSet].insert(*it); } sets_[to].swap(sets_[biggerSet]); sets_[from].clear(); } int findAncestor(int from) { if (parents_[from] != from) parents_[from] = findAncestor(parents_[from]); return parents_[from]; } private: vector<int> parents_; vector<set<SetType> > &sets_; }; int main() { int n, m, k; scanf("%d %d %d", &n, &m, &k); substanceWeights.resize(n); for (int i = 0 ; i < n ; i++) { int substanceWeight; scanf("%d", &substanceWeight); substanceWeights[i] = substanceWeight; } vector<pair<int,int> > joinFromTo; joinFromTo.reserve(m); for (int i = 0 ; i < m ; i++) { int from, to; scanf("%d %d", &from, &to); joinFromTo.push_back(make_pair(--from, --to)); } vector<set<Triple> > substitutes(n); for (int i = 0 ; i < k ; i++) { int sub1, sub2; scanf("%d %d", &sub1, &sub2); --sub1; --sub2; substitutes[sub1].insert(Triple(i, sub2, sub1)); substitutes[sub2].insert(Triple(i, sub1, sub2)); } ListJoinSets<Triple> listJoinSets(n, substitutes); for (int i = 0 ; i < m ; i++) { listJoinSets.join(joinFromTo[i].first, joinFromTo[i].second); } printf("%lld\n", result); }
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 | #include <cstdio> #include <vector> #include <algorithm> #include <set> using namespace std; long long result = 0LL; std::vector<int> substanceWeights; struct Triple { Triple(int first_, int second_, int thrid_) : first(first_), second(second_), thrid(thrid_) { } int first, second, thrid; bool operator <(Triple p) const { return first < p.first; } }; template <typename SetType> struct ListJoinSets { ListJoinSets(int n, vector<set<SetType> >& sets) : parents_(n), sets_(sets) { for (int i = 0 ; i < n ; i++) parents_[i] = i; } void join(int from, int to) { //assert(parents_[from] == from); parents_[from] = to; int smallerSet = sets_[from].size() < sets_[to].size() ? from : to; int biggerSet = sets_[from].size() >= sets_[to].size() ? from : to; for (typename set<SetType>::iterator it = sets_[smallerSet].begin() ; it != sets_[smallerSet].end() ; ++it) { if (findAncestor(it->second) == to) { int weight = min(substanceWeights[it->second], substanceWeights[it->thrid]); result += 2 * weight; substanceWeights[it->second] -= weight; substanceWeights[it->thrid] -= weight; } else sets_[biggerSet].insert(*it); } sets_[to].swap(sets_[biggerSet]); sets_[from].clear(); } int findAncestor(int from) { if (parents_[from] != from) parents_[from] = findAncestor(parents_[from]); return parents_[from]; } private: vector<int> parents_; vector<set<SetType> > &sets_; }; int main() { int n, m, k; scanf("%d %d %d", &n, &m, &k); substanceWeights.resize(n); for (int i = 0 ; i < n ; i++) { int substanceWeight; scanf("%d", &substanceWeight); substanceWeights[i] = substanceWeight; } vector<pair<int,int> > joinFromTo; joinFromTo.reserve(m); for (int i = 0 ; i < m ; i++) { int from, to; scanf("%d %d", &from, &to); joinFromTo.push_back(make_pair(--from, --to)); } vector<set<Triple> > substitutes(n); for (int i = 0 ; i < k ; i++) { int sub1, sub2; scanf("%d %d", &sub1, &sub2); --sub1; --sub2; substitutes[sub1].insert(Triple(i, sub2, sub1)); substitutes[sub2].insert(Triple(i, sub1, sub2)); } ListJoinSets<Triple> listJoinSets(n, substitutes); for (int i = 0 ; i < m ; i++) { listJoinSets.join(joinFromTo[i].first, joinFromTo[i].second); } printf("%lld\n", result); } |