#pragma once
#include"../data-structure/skew-heap.hpp"
#include"../data-structure/union-find.hpp"
#include"graph-template.hpp"template<typenameT>Edges<T>MinimumCostArborescence(intN,introot,constEdges<T>&es){usingHeap=SkewHeap<T>;usingPtr=typenameHeap::Ptr;UnionFinduf(N);vector<int>used(N,-1),from(N);vector<T>from_cost(N);vector<Ptr>come(N,nullptr);used[root]=root;vector<int>par_e(es.size(),-1),stem(N,-1),idxs;for(inti=0;i<(int)es.size();i++){auto&e=es[i];come[e]=Heap::push(come[e],e.cost,i);}Tcosts=0;for(intstart=0;start<N;start++){if(used[start]!=-1)continue;intcur=start;vector<int>chi_e;intcycle=0;while(used[cur]==-1||used[cur]==start){used[cur]=start;if(come[cur]==nullptr)return{};intsrc=uf.find(es[come[cur]->idx].src);Tcost=come[cur]->key+come[cur]->laz;intidx=come[cur]->idx;come[cur]=Heap::pop(come[cur]);if(src==cur)continue;from[cur]=src;from_cost[cur]=cost;if(stem[cur]==-1)stem[cur]=idx;costs+=cost;idxs.push_back(idx);while(cycle){par_e[chi_e.back()]=idx;chi_e.pop_back();--cycle;}chi_e.push_back(idx);if(used[src]==start){intp=cur;do{if(come[p])Heap::apply(come[p],-from_cost[p]);if(p!=cur){uf.unite(p,cur);Ptrnewheap=Heap::meld(come[cur],come[p]);come[cur=uf.find(cur)]=newheap;}p=uf.find(from[p]);++cycle;}while(p!=cur);}else{cur=src;}}}vector<int>used_e(es.size());Edges<T>res;for(int_=(int)idxs.size();_--;){intidx=idxs[_];if(used_e[idx])continue;auto&e=es[idx];res.push_back(e);intx=stem[e.to];while(x!=idx){used_e[x]=true;x=par_e[x];}}returnres;}
#line 2 "graph/minimum-cost-arborescence.hpp"
#line 2 "data-structure/skew-heap.hpp"
template<typenameT,boolisMin=true>structSkewHeap{structNode{Tkey,laz;Node*l,*r;intidx;Node()=default;Node(constT&k,inti=-1):key(k),laz(0),l(nullptr),r(nullptr),idx(i){}};usingPtr=Node*;staticvoidpropagate(Ptrx){if(x->laz==0)return;if(x->l)x->l->laz+=x->laz;if(x->r)x->r->laz+=x->laz;x->key+=x->laz;x->laz=0;}staticPtrmeld(Ptrx,Ptry){if(!x||!y)returnx?x:y;if(!comp(x,y))swap(x,y);propagate(x);x->r=meld(x->r,y);swap(x->l,x->r);returnx;}staticPtralloc(constT&key,intidx=-1){returnnewNode(key,idx);}staticPtrpop(Ptrx){propagate(x);returnmeld(x->l,x->r);}staticPtrpush(Ptrx,constT&key,intidx=-1){returnmeld(x,alloc(key,idx));}staticvoidapply(Ptrx,constT&laz){x->laz+=laz;propagate(x);}private:staticinlineboolcomp(Ptrx,Ptry){ifconstexpr(isMin){returnx->key+x->laz<y->key+y->laz;}else{returnx->key+x->laz>y->key+y->laz;}}};/**
* @brief Skew Heap
* @docs docs/data-structure/skew-heap.md
*/#line 2 "data-structure/union-find.hpp"
structUnionFind{vector<int>data;UnionFind(intN):data(N,-1){}intfind(intk){returndata[k]<0?k:data[k]=find(data[k]);}intunite(intx,inty){if((x=find(x))==(y=find(y)))returnfalse;if(data[x]>data[y])swap(x,y);data[x]+=data[y];data[y]=x;returntrue;}// f(x, y) : x に y をマージtemplate<typenameF>intunite(intx,inty,constF&f){if((x=find(x))==(y=find(y)))returnfalse;if(data[x]>data[y])swap(x,y);data[x]+=data[y];data[y]=x;f(x,y);returntrue;}intsize(intk){return-data[find(k)];}intsame(intx,inty){returnfind(x)==find(y);}};/**
* @brief Union Find(Disjoint Set Union)
* @docs docs/data-structure/union-find.md
*/#line 2 "graph/graph-template.hpp"
template<typenameT>structedge{intsrc,to;Tcost;edge(int_to,T_cost):src(-1),to(_to),cost(_cost){}edge(int_src,int_to,T_cost):src(_src),to(_to),cost(_cost){}edge&operator=(constint&x){to=x;return*this;}operatorint()const{returnto;}};template<typenameT>usingEdges=vector<edge<T>>;template<typenameT>usingWeightedGraph=vector<Edges<T>>;usingUnweightedGraph=vector<vector<int>>;// Input of (Unweighted) GraphUnweightedGraphgraph(intN,intM=-1,boolis_directed=false,boolis_1origin=true){UnweightedGraphg(N);if(M==-1)M=N-1;for(int_=0;_<M;_++){intx,y;cin>>x>>y;if(is_1origin)x--,y--;g[x].push_back(y);if(!is_directed)g[y].push_back(x);}returng;}// Input of Weighted Graphtemplate<typenameT>WeightedGraph<T>wgraph(intN,intM=-1,boolis_directed=false,boolis_1origin=true){WeightedGraph<T>g(N);if(M==-1)M=N-1;for(int_=0;_<M;_++){intx,y;cin>>x>>y;Tc;cin>>c;if(is_1origin)x--,y--;g[x].emplace_back(x,y,c);if(!is_directed)g[y].emplace_back(y,x,c);}returng;}// Input of Edgestemplate<typenameT>Edges<T>esgraph([[maybe_unused]]intN,intM,intis_weighted=true,boolis_1origin=true){Edges<T>es;for(int_=0;_<M;_++){intx,y;cin>>x>>y;Tc;if(is_weighted)cin>>c;elsec=1;if(is_1origin)x--,y--;es.emplace_back(x,y,c);}returnes;}// Input of Adjacency Matrixtemplate<typenameT>vector<vector<T>>adjgraph(intN,intM,TINF,intis_weighted=true,boolis_directed=false,boolis_1origin=true){vector<vector<T>>d(N,vector<T>(N,INF));for(int_=0;_<M;_++){intx,y;cin>>x>>y;Tc;if(is_weighted)cin>>c;elsec=1;if(is_1origin)x--,y--;d[x][y]=c;if(!is_directed)d[y][x]=c;}returnd;}/**
* @brief グラフテンプレート
* @docs docs/graph/graph-template.md
*/#line 6 "graph/minimum-cost-arborescence.hpp"
template<typenameT>Edges<T>MinimumCostArborescence(intN,introot,constEdges<T>&es){usingHeap=SkewHeap<T>;usingPtr=typenameHeap::Ptr;UnionFinduf(N);vector<int>used(N,-1),from(N);vector<T>from_cost(N);vector<Ptr>come(N,nullptr);used[root]=root;vector<int>par_e(es.size(),-1),stem(N,-1),idxs;for(inti=0;i<(int)es.size();i++){auto&e=es[i];come[e]=Heap::push(come[e],e.cost,i);}Tcosts=0;for(intstart=0;start<N;start++){if(used[start]!=-1)continue;intcur=start;vector<int>chi_e;intcycle=0;while(used[cur]==-1||used[cur]==start){used[cur]=start;if(come[cur]==nullptr)return{};intsrc=uf.find(es[come[cur]->idx].src);Tcost=come[cur]->key+come[cur]->laz;intidx=come[cur]->idx;come[cur]=Heap::pop(come[cur]);if(src==cur)continue;from[cur]=src;from_cost[cur]=cost;if(stem[cur]==-1)stem[cur]=idx;costs+=cost;idxs.push_back(idx);while(cycle){par_e[chi_e.back()]=idx;chi_e.pop_back();--cycle;}chi_e.push_back(idx);if(used[src]==start){intp=cur;do{if(come[p])Heap::apply(come[p],-from_cost[p]);if(p!=cur){uf.unite(p,cur);Ptrnewheap=Heap::meld(come[cur],come[p]);come[cur=uf.find(cur)]=newheap;}p=uf.find(from[p]);++cycle;}while(p!=cur);}else{cur=src;}}}vector<int>used_e(es.size());Edges<T>res;for(int_=(int)idxs.size();_--;){intidx=idxs[_];if(used_e[idx])continue;auto&e=es[idx];res.push_back(e);intx=stem[e.to];while(x!=idx){used_e[x]=true;x=par_e[x];}}returnres;}