This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub beet-aizu/library
#ifndef call_from_test #include <bits/stdc++.h> using namespace std; #endif //BEGIN CUT HERE template<typename T> struct Arborescence{ struct SkewHeap{ using P = pair<T, int>; const P INF; const T add_identity; SkewHeap(T inf):INF(inf,-1),add_identity(0){} struct Node{ Node *l,*r; P val; T add; Node(P val,T add):val(val),add(add){l=r=nullptr;} }; P reflect(P x,T y){return P(x.first+y,x.second);} void eval(Node *a){ if(a==nullptr) return; if(a->add==add_identity) return; if(a->l) a->l->add+=a->add; if(a->r) a->r->add+=a->add; a->val=reflect(a->val,a->add); a->add=add_identity; } P top(Node *a){ return a?reflect(a->val,a->add):INF; } P snd(Node *a){ eval(a); return a?min(top(a->l),top(a->r)):INF; } Node* add(Node *a,T d){ if(a) a->add+=d; return a; } Node* push(T v,int i){ return new Node(P(v,i),add_identity); } Node* meld(Node *a,Node *b){ if(!a or !b) return a?a:b; if(top(b)<top(a)) swap(a,b); eval(a); a->r=meld(a->r,b); swap(a->l,a->r); return a; } Node* pop(Node* a){ eval(a); auto res=meld(a->l,a->r); delete a; return res; } }; struct UnionFind{ vector<int> r,p; UnionFind(int sz):r(sz,1),p(sz,0){iota(p.begin(),p.end(),0);} int find(int x){ return (x==p[x]?x:p[x]=find(p[x])); } bool same(int x,int y){ return find(x)==find(y); } void unite(int x,int y){ x=find(x);y=find(y); if(x==y) return; r[x]+=r[y]; p[y]=x; } }; struct edge{ int from,to; T cost; edge(int from,int to,T cost):from(from),to(to),cost(cost){} }; int n; vector<edge> es; Arborescence(int n):n(n){}; void add_edge(int from,int to,T cost){ es.emplace_back(from,to,cost); } T build(int r){ UnionFind uf(n); const T INF = numeric_limits<T>::max()/2; SkewHeap hp(INF); vector<typename SkewHeap::Node*> come(n,nullptr); vector<int> used(n,0),from(n,-1); vector<T> cost(n,-1); used[r]=2; for(int i=0;i<(int)es.size();i++){ edge &e=es[i]; come[e.to]=hp.meld(come[e.to],hp.push(e.cost,i)); } T res=0; for(int i=0;i<n;i++){ if(used[i]) continue; int v=i; vector<int> l; while(used[v]!=2){ used[v]=1; l.emplace_back(v); if(!come[v]) return T(-1); from[v]=uf.find(es[come[v]->val.second].from); cost[v]=hp.top(come[v]).first; come[v]=hp.pop(come[v]); if(from[v]==v) continue; res+=cost[v]; if(used[from[v]]==1){ int p=v; do{ if(come[p]!=nullptr) hp.add(come[p],-cost[p]); if(p!=v){ uf.unite(v,p); come[v]=hp.meld(come[v],come[p]); } p=uf.find(from[p]); }while(p!=v); }else{ v=from[v]; } } for(int u:l) used[u]=2; } return res; } }; //END CUT HERE #ifndef call_from_test //INSERT ABOVE HERE signed UVA_11183(){ using ll = long long; int T; cin>>T; for(int t=1;t<=T;t++){ int n,m; cin>>n>>m; Arborescence<ll> G(n); for(int i=0;i<m;i++){ int s,t,w; cin>>s>>t>>w; G.add_edge(s,t,w); } ll ans=G.build(0); cout<<"Case #"<<t<<": "; if(ans<0) cout<<"Possums!"<<endl; else cout<<ans<<endl; } return 0; } /* verified on 2019/12/17 https://vjudge.net/problem/UVA-11183 */ signed main(){ //UVA_11183(); return 0; } #endif
#line 1 "graph/arborescence_tarjan.cpp" #include <bits/stdc++.h> using namespace std; #endif //BEGIN CUT HERE template<typename T> struct Arborescence{ struct SkewHeap{ using P = pair<T, int>; const P INF; const T add_identity; SkewHeap(T inf):INF(inf,-1),add_identity(0){} struct Node{ Node *l,*r; P val; T add; Node(P val,T add):val(val),add(add){l=r=nullptr;} }; P reflect(P x,T y){return P(x.first+y,x.second);} void eval(Node *a){ if(a==nullptr) return; if(a->add==add_identity) return; if(a->l) a->l->add+=a->add; if(a->r) a->r->add+=a->add; a->val=reflect(a->val,a->add); a->add=add_identity; } P top(Node *a){ return a?reflect(a->val,a->add):INF; } P snd(Node *a){ eval(a); return a?min(top(a->l),top(a->r)):INF; } Node* add(Node *a,T d){ if(a) a->add+=d; return a; } Node* push(T v,int i){ return new Node(P(v,i),add_identity); } Node* meld(Node *a,Node *b){ if(!a or !b) return a?a:b; if(top(b)<top(a)) swap(a,b); eval(a); a->r=meld(a->r,b); swap(a->l,a->r); return a; } Node* pop(Node* a){ eval(a); auto res=meld(a->l,a->r); delete a; return res; } }; struct UnionFind{ vector<int> r,p; UnionFind(int sz):r(sz,1),p(sz,0){iota(p.begin(),p.end(),0);} int find(int x){ return (x==p[x]?x:p[x]=find(p[x])); } bool same(int x,int y){ return find(x)==find(y); } void unite(int x,int y){ x=find(x);y=find(y); if(x==y) return; r[x]+=r[y]; p[y]=x; } }; struct edge{ int from,to; T cost; edge(int from,int to,T cost):from(from),to(to),cost(cost){} }; int n; vector<edge> es; Arborescence(int n):n(n){}; void add_edge(int from,int to,T cost){ es.emplace_back(from,to,cost); } T build(int r){ UnionFind uf(n); const T INF = numeric_limits<T>::max()/2; SkewHeap hp(INF); vector<typename SkewHeap::Node*> come(n,nullptr); vector<int> used(n,0),from(n,-1); vector<T> cost(n,-1); used[r]=2; for(int i=0;i<(int)es.size();i++){ edge &e=es[i]; come[e.to]=hp.meld(come[e.to],hp.push(e.cost,i)); } T res=0; for(int i=0;i<n;i++){ if(used[i]) continue; int v=i; vector<int> l; while(used[v]!=2){ used[v]=1; l.emplace_back(v); if(!come[v]) return T(-1); from[v]=uf.find(es[come[v]->val.second].from); cost[v]=hp.top(come[v]).first; come[v]=hp.pop(come[v]); if(from[v]==v) continue; res+=cost[v]; if(used[from[v]]==1){ int p=v; do{ if(come[p]!=nullptr) hp.add(come[p],-cost[p]); if(p!=v){ uf.unite(v,p); come[v]=hp.meld(come[v],come[p]); } p=uf.find(from[p]); }while(p!=v); }else{ v=from[v]; } } for(int u:l) used[u]=2; } return res; } }; //END CUT HERE #ifndef call_from_test //INSERT ABOVE HERE signed UVA_11183(){ using ll = long long; int T; cin>>T; for(int t=1;t<=T;t++){ int n,m; cin>>n>>m; Arborescence<ll> G(n); for(int i=0;i<m;i++){ int s,t,w; cin>>s>>t>>w; G.add_edge(s,t,w); } ll ans=G.build(0); cout<<"Case #"<<t<<": "; if(ans<0) cout<<"Possums!"<<endl; else cout<<ans<<endl; } return 0; } /* verified on 2019/12/17 https://vjudge.net/problem/UVA-11183 */ signed main(){ //UVA_11183(); return 0; } #endif