#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define popcount __builtin_popcount using namespace std; typedef long long int ll; typedef pair P; template struct MinCostFlow{ struct edge{ int to, rev; int num; Flow flow; Flow cap; Cost cost; edge(int to, Flow flow, Flow cap, Cost cost, int rev, int num):to(to), flow(flow), cap(cap), cost(cost), rev(rev), num(num){} }; int n; vector> g; vector b; vector h, dist; vector prevv, preve; MinCostFlow(int n):n(n), b(n), g(n), h(n), dist(n), prevv(n), preve(n){} void add_edge(int from, int to, Flow lower, Flow upper, Cost cost, int num){ int num1=g[to].size(), num2=g[from].size(); if(to==from) num1++; g[from].push_back(edge(to, lower, upper, cost, num1, num)); g[to].push_back(edge(from, -lower, -lower, -cost, num2, -num)); b[from]-=lower; b[to]+=lower; } Flow mx; bool dual(){ using P=pair; priority_queue, greater

> que; const Cost INF=1e18; fill(dist.begin(), dist.end(), INF); fill(prevv.begin(), prevv.end(), -1); for(int x=0; x0){ que.push({0, x}); dist[x]=0; } } mx=0; int cnt=0; while(!que.empty()){ auto p=que.top(); que.pop(); int x=p.second; if(dist[x]dist[x]+e.cost+h[x]-h[y]){ dist[y]=dist[x]+e.cost+h[x]-h[y]; que.push({dist[y], y}); prevv[y]=x; preve[y]=i; } } } if(cnt==0) return false; for(int x=0; xmx) continue; Flow f=-b[x]; int v; for(v=x; prevv[v]!=-1; v=prevv[v]){ edge &e=g[prevv[v]][preve[v]]; f=min(f, e.cap-e.flow); } f=min(f, b[v]); if(f==0) continue; for(v=x; prevv[v]!=-1; v=prevv[v]){ edge &e=g[prevv[v]][preve[v]]; e.flow+=f; g[v][e.rev].flow-=f; } b[v]-=f; b[x]+=f; } } bool solve(){ for(int x=0; x0){ b[x]-=(e.cap-e.flow); b[e.to]+=(e.cap-e.flow); g[e.to][e.rev].flow-=(e.cap-e.flow); e.flow=e.cap; } } } while(dual()) primal(); for(int x=0; x T calc(){ T ans=0; for(int x=0; x>n; cin>>str; for(int i=0; i>v[i]; vector w[5]; for(int i=0; i mcf(n+1); int s=w[0][0], t=n; w[4].push_back(t); ll ans=0; for(int k=0; k<4; k++){ for(int i=0; i<(int)w[k].size()-1; i++){ mcf.add_edge(w[k][i], w[k][i+1], 0, n/4, 0, 0); } for(int i:w[k]){ int j=lower_bound(w[k+1].begin(), w[k+1].end(), i)-w[k+1].begin(); if(j()<