#pragma once
#include"src/flows/dinic.hpp"/**
* Author: Teetat T.
* Date: 2024-07-16
* Description: k-ary Optimization.
* minimize $\kappa + \sum_i \theta_i(x_i) + \sum_{i<j} \phi_{ij}(x_i,x_j)$
* where $x_i \in \{0,1,\ldots,k-1\}$ and $\phi_{i,j}$ is monge.
* A function $f$ is monge if $f(a,c)+f(b,d) \leq f(a,d)+f(b,c)$ for all $a < b$ and $c < d$.
* $\phi_{ij}(x-1,y)+\phi_{ij}(x,y+1) \leq \phi_{ij}(x-1,y+1)+\phi_{ij}(x,y)$.
* $\phi_{ij}(x,y)+\phi_{ij}(x-1,y+1)-\phi_{ij}(x-1,y)-\phi_{ij}(x,y+1) \geq 0$.
*/template<classT,boolminimize=true>structK_aryOptimization{staticconstexprTINF=numeric_limits<T>::max()/2;intn,s,t,buf;Tbase;vector<int>ks;vector<vector<int>>id;map<pair<int,int>,T>edges;K_aryOptimization(intn,intk){init(vector<int>(n,k));}K_aryOptimization(constvector<int>&_ks){init(_ks);}voidinit(constvector<int>&_ks){ks=_ks;n=ks.size();s=0,t=1,buf=2;base=0;id.clear();edges.clear();for(auto&k:ks){assert(k>=1);vector<int>a(k+1);a[0]=s,a[k]=t;for(inti=1;i<k;i++)a[i]=buf++;id.emplace_back(a);for(inti=2;i<k;i++)add_edge(a[i],a[i-1],INF);}}voidadd_edge(intu,intv,Tw){assert(w>=0);if(u==v||w==0)return;auto&e=edges[{u,v}];e=min(e+w,INF);}voidadd0(Tw){base+=w;}void_add1(inti,vector<T>cost){add0(cost[0]);for(intj=1;j<ks[i];j++){Tx=cost[j]-cost[j-1];if(x>0)add_edge(id[i][j],t,x);if(x<0)add0(x),add_edge(s,id[i][j],-x);}}voidadd1(inti,vector<T>cost){assert(0<=i&&i<n&&(int)cost.size()==ks[i]);if(!minimize)for(auto&x:cost)x=-x;_add1(i,cost);}void_add2(inti,intj,vector<vector<T>>cost){inth=ks[i],w=ks[j];_add1(j,cost[0]);for(intx=h-1;x>=0;x--)for(inty=0;y<w;y++)cost[x][y]-=cost[0][y];vector<T>a(h);for(intx=0;x<h;x++)a[x]=cost[x][w-1];_add1(i,a);for(intx=0;x<h;x++)for(inty=0;y<w;y++)cost[x][y]-=a[x];for(intx=1;x<h;x++){for(inty=0;y<w-1;y++){Tw=cost[x][y]+cost[x-1][y+1]-cost[x-1][y]-cost[x][y+1];assert(w>=0);// mongeadd_edge(id[i][x],id[j][y+1],w);}}}voidadd2(inti,intj,vector<vector<T>>cost){assert(0<=i&&i<n&&0<=j&&j<n&&i!=j);assert((int)cost.size()==ks[i]);for(auto&v:cost)assert((int)v.size()==ks[j]);if(!minimize)for(auto&v:cost)for(auto&x:v)x=-x;_add2(i,j,cost);}pair<T,vector<int>>solve(){Dinic<T>dinic(buf,s,t);for(auto&[p,w]:edges){auto[u,v]=p;dinic.add_edge(u,v,w);}auto[val,cut]=dinic.cut();val+=base;if(!minimize)val=-val;vector<int>ans(n);for(inti=0;i<n;i++){ans[i]=ks[i]-1;for(intj=1;j<ks[i];j++)ans[i]-=cut[id[i][j]];}return{val,ans};}};
#line 2 "src/flows/dinic.hpp"
/**
* Author: Teetat T.
* Date: 2024-07-15
* Description: Dinic's Algorithm for finding the maximum flow.
* Time: O(V E \log U) where U is the maximum flow.
*/template<classT,booldirected=true,boolscaling=true>structDinic{staticconstexprTINF=numeric_limits<T>::max()/2;structEdge{intto;Tflow,cap;Edge(int_to,T_cap):to(_to),flow(0),cap(_cap){}Tremain(){returncap-flow;}};intn,s,t;TU;vector<Edge>e;vector<vector<int>>g;vector<int>ptr,lv;boolcalculated;Tmax_flow;Dinic(){}Dinic(intn,ints,intt){init(n,s,t);}voidinit(int_n,int_s,int_t){n=_n,s=_s,t=_t;U=0;e.clear();g.assign(n,{});calculated=false;}voidadd_edge(intfrom,intto,Tcap){assert(0<=from&&from<n&&0<=to&&to<n);g[from].emplace_back(e.size());e.emplace_back(to,cap);g[to].emplace_back(e.size());e.emplace_back(from,directed?0:cap);U=max(U,cap);}boolbfs(Tscale){lv.assign(n,-1);vector<int>q{s};lv[s]=0;for(inti=0;i<(int)q.size();i++){intu=q[i];for(intj:g[u]){intv=e[j].to;if(lv[v]==-1&&e[j].remain()>=scale){q.emplace_back(v);lv[v]=lv[u]+1;}}}returnlv[t]!=-1;}Tdfs(intu,intt,Tf){if(u==t||f==0)returnf;for(int&i=ptr[u];i<(int)g[u].size();i++){intj=g[u][i];intv=e[j].to;if(lv[v]==lv[u]+1){Tres=dfs(v,t,min(f,e[j].remain()));if(res>0){e[j].flow+=res;e[j^1].flow-=res;returnres;}}}return0;}Tflow(){if(calculated)returnmax_flow;calculated=true;max_flow=0;for(Tscale=scaling?1LL<<(63-__builtin_clzll(U)):1LL;scale>0;scale>>=1){while(bfs(scale)){ptr.assign(n,0);while(true){Tf=dfs(s,t,INF);if(f==0)break;max_flow+=f;}}}returnmax_flow;}pair<T,vector<int>>cut(){flow();vector<int>res(n);for(inti=0;i<n;i++)res[i]=(lv[i]==-1);return{max_flow,res};}};#line 3 "src/flows/k-ary-optimization.hpp"
/**
* Author: Teetat T.
* Date: 2024-07-16
* Description: k-ary Optimization.
* minimize $\kappa + \sum_i \theta_i(x_i) + \sum_{i<j} \phi_{ij}(x_i,x_j)$
* where $x_i \in \{0,1,\ldots,k-1\}$ and $\phi_{i,j}$ is monge.
* A function $f$ is monge if $f(a,c)+f(b,d) \leq f(a,d)+f(b,c)$ for all $a < b$ and $c < d$.
* $\phi_{ij}(x-1,y)+\phi_{ij}(x,y+1) \leq \phi_{ij}(x-1,y+1)+\phi_{ij}(x,y)$.
* $\phi_{ij}(x,y)+\phi_{ij}(x-1,y+1)-\phi_{ij}(x-1,y)-\phi_{ij}(x,y+1) \geq 0$.
*/template<classT,boolminimize=true>structK_aryOptimization{staticconstexprTINF=numeric_limits<T>::max()/2;intn,s,t,buf;Tbase;vector<int>ks;vector<vector<int>>id;map<pair<int,int>,T>edges;K_aryOptimization(intn,intk){init(vector<int>(n,k));}K_aryOptimization(constvector<int>&_ks){init(_ks);}voidinit(constvector<int>&_ks){ks=_ks;n=ks.size();s=0,t=1,buf=2;base=0;id.clear();edges.clear();for(auto&k:ks){assert(k>=1);vector<int>a(k+1);a[0]=s,a[k]=t;for(inti=1;i<k;i++)a[i]=buf++;id.emplace_back(a);for(inti=2;i<k;i++)add_edge(a[i],a[i-1],INF);}}voidadd_edge(intu,intv,Tw){assert(w>=0);if(u==v||w==0)return;auto&e=edges[{u,v}];e=min(e+w,INF);}voidadd0(Tw){base+=w;}void_add1(inti,vector<T>cost){add0(cost[0]);for(intj=1;j<ks[i];j++){Tx=cost[j]-cost[j-1];if(x>0)add_edge(id[i][j],t,x);if(x<0)add0(x),add_edge(s,id[i][j],-x);}}voidadd1(inti,vector<T>cost){assert(0<=i&&i<n&&(int)cost.size()==ks[i]);if(!minimize)for(auto&x:cost)x=-x;_add1(i,cost);}void_add2(inti,intj,vector<vector<T>>cost){inth=ks[i],w=ks[j];_add1(j,cost[0]);for(intx=h-1;x>=0;x--)for(inty=0;y<w;y++)cost[x][y]-=cost[0][y];vector<T>a(h);for(intx=0;x<h;x++)a[x]=cost[x][w-1];_add1(i,a);for(intx=0;x<h;x++)for(inty=0;y<w;y++)cost[x][y]-=a[x];for(intx=1;x<h;x++){for(inty=0;y<w-1;y++){Tw=cost[x][y]+cost[x-1][y+1]-cost[x-1][y]-cost[x][y+1];assert(w>=0);// mongeadd_edge(id[i][x],id[j][y+1],w);}}}voidadd2(inti,intj,vector<vector<T>>cost){assert(0<=i&&i<n&&0<=j&&j<n&&i!=j);assert((int)cost.size()==ks[i]);for(auto&v:cost)assert((int)v.size()==ks[j]);if(!minimize)for(auto&v:cost)for(auto&x:v)x=-x;_add2(i,j,cost);}pair<T,vector<int>>solve(){Dinic<T>dinic(buf,s,t);for(auto&[p,w]:edges){auto[u,v]=p;dinic.add_edge(u,v,w);}auto[val,cut]=dinic.cut();val+=base;if(!minimize)val=-val;vector<int>ans(n);for(inti=0;i<n;i++){ans[i]=ks[i]-1;for(intj=1;j<ks[i];j++)ans[i]-=cut[id[i][j]];}return{val,ans};}};