#include using namespace std; const int MAXN=100000+5; const int MOD=(1<<10)-1; int n,T,a[4]; char s[MAXN][4]; namespace Flow { const int MAXL=100; const int MAXE=MAXL<<5; const int INF=1<<30; int S,T,cnt=1,fir[MAXL],cur[MAXL],dis[MAXL]; struct Edge { int flow,cost,to,nxt; }e[MAXE]; bool vis[MAXL],inq[MAXL]; void add(int x,int y,int w,int c) { e[++cnt]=(Edge){w,c,y,fir[x]}; fir[x]=cnt; e[++cnt]=(Edge){0,-c,x,fir[y]}; fir[y]=cnt; } bool bfs() { queueq; for(int i=0;i<=T;i++) dis[i]=INF,cur[i]=fir[i],vis[i]=inq[i]=0; q.push(S); dis[S]=0; while(q.size()) { int x=q.front();q.pop();inq[x]=0; for(int i=fir[x];i;i=e[i].nxt) { int v=e[i].to; if(e[i].flow>0&&dis[v]>dis[x]+e[i].cost) { dis[v]=dis[x]+e[i].cost; if(!inq[v]) q.push(v),inq[v]=1; } } } return dis[T]!=INF; } int dfs(int x,int flow) { if(x==T||!flow) return flow; vis[x]=1; int all=flow; for(int &i=cur[x];i;i=e[i].nxt) { int v=e[i].to; if(dis[v]!=dis[x]+e[i].cost||vis[v]) continue; int now=dfs(v,min(flow,e[i].flow)); flow-=now; e[i].flow-=now; e[i^1].flow+=now; if(!flow) {vis[x]=0;return all-flow;} } return all-flow; } void clr(int n) { S=0;T=n+1; for(int i=0;i<=T;i++) fir[i]=vis[i]=0; cnt=1; } pairGet() { pairres=make_pair(0,0); while(bfs()) { int s=dfs(S,INF); res.first+=s; res.second+=s*dis[T]; } return res; } } void solve() { scanf("%d",&n); scanf("%d%d%d",&a[0],&a[1],&a[2]); Flow::clr(9); maphs; for(int i=1;i<=n;i++) { scanf("%s",s[i]); int pos=(s[i][0]-'0'+1)*1000000+(s[i][1]-'0'+1)*1000+(s[i][2]-'0'+1); hs[pos]++; } Flow::add(1,Flow::T,a[0],0); Flow::add(2,Flow::T,a[1],0); Flow::add(3,Flow::T,a[2],0); int cc=3; for(map::iterator it=hs.begin();it!=hs.end();it++) { ++cc;int id=it->first; Flow::add(Flow::S,cc,it->second,0); Flow::add(cc,id%1000,it->second,-1); id/=1000; Flow::add(cc,id%1000,it->second,-2); id/=1000; Flow::add(cc,id%1000,it->second,-3); } printf("%d\n",-Flow::Get().second); } int main() { scanf("%d",&T); while(T--) solve(); return 0; }