#pragma once
#include"library/datastructure/unionfind/UnionFind.hpp"template<typenameWG,typenameW=typenameWG::weight_type>std::optional<std::pair<W,std::vector<int>>>minimum_spanning_arborescence(WGg,intr=0){intn=g.n;Wres=0;std::vector<W>new_add(n,0);std::vector<int>tree(n),pre(n),state(n,0);UnionFinduf(n);state[r]=2;autocompare=[&](constint&a,constint&b){returng.edges[a].weight>g.edges[b].weight;};usingPQ=std::priority_queue<int,std::vector<int>,decltype(compare)>;std::vector<std::pair<PQ,W>>pq_add(n,{PQ{compare},0});for(inti=0;i<g.edges.size();i++)pq_add[g.edges[i].to].first.push(i);std::vector<int>pq_id(n);std::iota(pq_id.begin(),pq_id.end(),0);automerge=[&](intu,intv){u=uf.leader(u);v=uf.leader(v);if(u==v)return;uf.merge(u,v);auto&[pq1,add1]=pq_add[pq_id[u]];auto&[pq2,add2]=pq_add[pq_id[v]];if(pq1.size()>pq2.size()){while(pq2.size()){intedge_id=pq2.top();pq2.pop();g.edges[edge_id].weight-=add2-add1;pq1.push(edge_id);}pq_id[uf.leader(v)]=pq_id[u];}else{while(pq1.size()){intedge_id=pq1.top();pq1.pop();g.edges[edge_id].weight-=add1-add2;pq2.push(edge_id);}pq_id[uf.leader(v)]=pq_id[v];}};for(inti=0;i<n;i++){intnow=uf.leader(i);if(state[now])continue;std::vector<int>processing;while(state[now]!=2){processing.push_back(now);state[now]=1;auto&[pq,add]=pq_add[pq_id[now]];if(!pq.size())returnstd::nullopt;intedge_id=pq.top();pq.pop();auto&e=g.edges[edge_id];res+=e.weight-add;tree[e.to]=edge_id;pre[now]=uf.leader(e.from);new_add[now]=e.weight;if(state[pre[now]]==1){intv=now;do{pq_add[pq_id[v]].second=new_add[v];merge(v,now);v=uf.leader(pre[v]);}while(!uf.same(v,now));now=uf.leader(now);}elsenow=uf.leader(pre[now]);}for(intv:processing)state[v]=2;}tree.erase(tree.begin()+r);returnstd::make_pair(res,tree);}