// Author: Adam Krasuski #include <cstdio> #include <vector> #include <map> #include <set> using namespace std; struct tube{ map<int,int>contents; int total_edges; }; struct edge{ int from; int to; int priority; }; bool operator<(edge a,edge b){ return a.priority<b.priority; } #define DEBUG 1 int print_tubes(vector<tube>tubes){ if(DEBUG){ printf("\nTubes now are:"); for(int i=0;i<tubes.size();i++){ printf("\nTube %d:\n",i); printf("-total_edges=%d\n",tubes[i].total_edges); printf("Contents: "); for(map<int,int>::iterator it=tubes[i].contents.begin();it!=tubes[i].contents.end();it++){ printf("%d(%dg) ",it->first,it->second); } } } } vector<edge>reactions[200009]; int main(){ int n,m,k; scanf("%d %d %d",&n,&m,&k); vector<tube>tubes; for(int i=0;i<n;i++){ int g; scanf("%d",&g); map<int,int>mc; mc[i]=g;//mass of ith substance in the tube is g tube t1={mc,0}; tubes.push_back(t1); } vector<int>move_from,move_to; for(int i=0;i<m;i++){ int a,b; scanf("%d %d",&a,&b); a--;b--; move_from.push_back(a); move_to.push_back(b); } //print_tubes(tubes); for(int i=0;i<k;i++){ int c,d; scanf("%d %d",&c,&d); c--;d--; edge ed={c,d,i}; reactions[c].push_back(ed); ed.from=d; ed.to=c; reactions[d].push_back(ed); tubes[c].total_edges++; tubes[d].total_edges++; } //print_tubes(tubes); long long int total_precipitate=0; for(int i=0;i<m;i++){ //answering moves int mf=move_from[i]; int mt=move_to[i]; tube t1=tubes[mf]; tube t2=tubes[mt]; bool t1_smaller=(t1.contents.size()<t2.contents.size()); bool t1_edges_count_smaller=(t1.total_edges<t2.total_edges); set<edge>edges_to_be_checked; if(t1_edges_count_smaller){ //check t1 edges for(map<int,int>::iterator it=t1.contents.begin();it!=t1.contents.end();it++){ int substance=it->first; for(int j=0;j<reactions[substance].size();j++){ int sub2=reactions[substance][j].to; if(t2.contents.count(sub2)>0){ edges_to_be_checked.insert(reactions[substance][j]); } } } } else{ //check t2 edges for(map<int,int>::iterator it=t2.contents.begin();it!=t2.contents.end();it++){ int substance=it->first; for(int j=0;j<reactions[substance].size();j++){ int sub2=reactions[substance][j].to; if(t1.contents.count(sub2)>0){ edges_to_be_checked.insert(reactions[substance][j]); } } } } if(t1_smaller){ //insert t1 into t2 t2.contents.insert(t1.contents.begin(),t1.contents.end()); } else{ //insert t2 into t1, and swap t1.contents.insert(t2.contents.begin(),t2.contents.end()); t1.contents.swap(t2.contents); } //now, t2 contains sum of t1 and t2 substances //now, take care of reactions for(set<edge>::iterator it=edges_to_be_checked.begin();it!=edges_to_be_checked.end();it++){ edge ed=*it; int precipitate_mass=min(t2.contents[(*it).from],t2.contents[(*it).to]); total_precipitate+=(long long int)precipitate_mass*2; t2.contents[(*it).from]-=precipitate_mass; t2.contents[(*it).to]-=precipitate_mass; } //remove the substances that are irrelevant now - i.e. those with mass equal to zero. for(map<int,int>::iterator it=t2.contents.begin();it!=t2.contents.end();it++){ if(it->second==0){//mass==0 t2.contents.erase(it); } } //count the number of edges from t2 contents int cnt=0; for(map<int,int>::iterator it=t2.contents.begin();it!=t2.contents.end();it++){ cnt+=reactions[ it->first ].size(); } t2.total_edges=cnt; //and update the tubes vector tubes[mt]=t2; } printf("%lld\n",total_precipitate); }
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 | // Author: Adam Krasuski #include <cstdio> #include <vector> #include <map> #include <set> using namespace std; struct tube{ map<int,int>contents; int total_edges; }; struct edge{ int from; int to; int priority; }; bool operator<(edge a,edge b){ return a.priority<b.priority; } #define DEBUG 1 int print_tubes(vector<tube>tubes){ if(DEBUG){ printf("\nTubes now are:"); for(int i=0;i<tubes.size();i++){ printf("\nTube %d:\n",i); printf("-total_edges=%d\n",tubes[i].total_edges); printf("Contents: "); for(map<int,int>::iterator it=tubes[i].contents.begin();it!=tubes[i].contents.end();it++){ printf("%d(%dg) ",it->first,it->second); } } } } vector<edge>reactions[200009]; int main(){ int n,m,k; scanf("%d %d %d",&n,&m,&k); vector<tube>tubes; for(int i=0;i<n;i++){ int g; scanf("%d",&g); map<int,int>mc; mc[i]=g;//mass of ith substance in the tube is g tube t1={mc,0}; tubes.push_back(t1); } vector<int>move_from,move_to; for(int i=0;i<m;i++){ int a,b; scanf("%d %d",&a,&b); a--;b--; move_from.push_back(a); move_to.push_back(b); } //print_tubes(tubes); for(int i=0;i<k;i++){ int c,d; scanf("%d %d",&c,&d); c--;d--; edge ed={c,d,i}; reactions[c].push_back(ed); ed.from=d; ed.to=c; reactions[d].push_back(ed); tubes[c].total_edges++; tubes[d].total_edges++; } //print_tubes(tubes); long long int total_precipitate=0; for(int i=0;i<m;i++){ //answering moves int mf=move_from[i]; int mt=move_to[i]; tube t1=tubes[mf]; tube t2=tubes[mt]; bool t1_smaller=(t1.contents.size()<t2.contents.size()); bool t1_edges_count_smaller=(t1.total_edges<t2.total_edges); set<edge>edges_to_be_checked; if(t1_edges_count_smaller){ //check t1 edges for(map<int,int>::iterator it=t1.contents.begin();it!=t1.contents.end();it++){ int substance=it->first; for(int j=0;j<reactions[substance].size();j++){ int sub2=reactions[substance][j].to; if(t2.contents.count(sub2)>0){ edges_to_be_checked.insert(reactions[substance][j]); } } } } else{ //check t2 edges for(map<int,int>::iterator it=t2.contents.begin();it!=t2.contents.end();it++){ int substance=it->first; for(int j=0;j<reactions[substance].size();j++){ int sub2=reactions[substance][j].to; if(t1.contents.count(sub2)>0){ edges_to_be_checked.insert(reactions[substance][j]); } } } } if(t1_smaller){ //insert t1 into t2 t2.contents.insert(t1.contents.begin(),t1.contents.end()); } else{ //insert t2 into t1, and swap t1.contents.insert(t2.contents.begin(),t2.contents.end()); t1.contents.swap(t2.contents); } //now, t2 contains sum of t1 and t2 substances //now, take care of reactions for(set<edge>::iterator it=edges_to_be_checked.begin();it!=edges_to_be_checked.end();it++){ edge ed=*it; int precipitate_mass=min(t2.contents[(*it).from],t2.contents[(*it).to]); total_precipitate+=(long long int)precipitate_mass*2; t2.contents[(*it).from]-=precipitate_mass; t2.contents[(*it).to]-=precipitate_mass; } //remove the substances that are irrelevant now - i.e. those with mass equal to zero. for(map<int,int>::iterator it=t2.contents.begin();it!=t2.contents.end();it++){ if(it->second==0){//mass==0 t2.contents.erase(it); } } //count the number of edges from t2 contents int cnt=0; for(map<int,int>::iterator it=t2.contents.begin();it!=t2.contents.end();it++){ cnt+=reactions[ it->first ].size(); } t2.total_edges=cnt; //and update the tubes vector tubes[mt]=t2; } printf("%lld\n",total_precipitate); } |