建出字典树,然后做最小割就行了...
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 5005;
const int maxm = 400005;
const int INF = 0x3f3f3f3f;
struct Edge
{
int v, c, next;
Edge() {}
Edge(int v, int c, int next) : v(v), c(c), next(next) {}
}E[maxm];
struct node
{
int id, val;
node *lson, *rson;
}pool[maxm], *tail, *rootA, *rootB;
queue<int> q;
int H[maxn], cntE;
int dis[maxn];
int cur[maxn];
int cnt[maxn];
int pre[maxn];
int n, m, s, t, flow, nv;
void addedges(int u, int v, int c)
{
E[cntE] = Edge(v, c, H[u]);
H[u] = cntE++;
E[cntE] = Edge(u, 0, H[v]);
H[v] = cntE++;
}
void bfs()
{
memset(cnt, 0, sizeof cnt);
memset(dis, -1, sizeof dis);
cnt[0]++, dis[t] = 0;
q.push(t);
while(!q.empty()) {
int u = q.front();
q.pop();
for(int e = H[u]; ~e; e = E[e].next) {
int v = E[e].v;
if(dis[v] == -1) {
dis[v] = dis[u] + 1;
cnt[dis[v]]++;
q.push(v);
}
}
}
}
int isap()
{
memcpy(cur, H, sizeof cur);
bfs();
flow = 0;
int u = pre[s] = s, f, minv, e, pos;
while(dis[s] < nv) {
if(u == t) {
f = INF;
for(int i = s; i != t; i = E[cur[i]].v) if(f > E[cur[i]].c) {
f = E[cur[i]].c;
pos = i;
}
for(int i = s; i != t; i = E[cur[i]].v) {
E[cur[i]].c -= f;
E[cur[i] ^ 1].c += f;
}
flow += f;
u = pos;
}
for(e = cur[u]; ~e; e = E[e].next) if(E[e].c && dis[E[e].v] + 1 == dis[u]) break;
if(~e) {
cur[u] = e;
pre[E[e].v] = u;
u = E[e].v;
}
else {
if(--cnt[dis[u]] == 0) break;
for(minv = nv, e = H[u]; ~e; e = E[e].next) if(E[e].c && minv > dis[E[e].v]) {
minv = dis[E[e].v];
cur[u] = e;
}
dis[u] = minv + 1;
cnt[dis[u]]++;
u = pre[u];
}
}
return flow;
}
void init()
{
cntE = 0;
memset(H, -1, sizeof H);
for(node *p = pool; p < tail; p++) p->val = INF;
}
node* newnode()
{
tail->id = tail - pool;
tail->lson = tail->rson = NULL;
return tail++;
}
node* dfs(int pos)
{
if(pos == 0) return NULL;
node *p = newnode();
p->lson = dfs(pos-1);
p->rson = dfs(pos-1);
return p;
}
void _ini()
{
tail = pool;
rootA = newnode();
rootA->lson = dfs(8);
rootA->rson = dfs(8);
rootB = newnode();
rootB->lson = dfs(8);
rootB->rson = dfs(8);
s = rootA->id, t = rootB->id;
nv = tail - pool;
}
void DFS(node *p, int flag)
{
if(p->lson) {
if(flag == 0) addedges(p->id, p->lson->id, p->lson->val);
else addedges(p->lson->id, p->id, p->lson->val);
DFS(p->lson, flag);
}
if(p->rson) {
if(flag == 0) addedges(p->id, p->rson->id, p->rson->val);
else addedges(p->rson->id, p->id, p->rson->val);
DFS(p->rson, flag);
}
}
char ss[100], op[100];
int a[300], b[300];
void work()
{
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 1; i <= m; i++) {
int val;
scanf("%s%s%d", op, ss, &val);
if(op[0] == 'P') {
node *p = rootA;
for(int j = 0; ss[j]; j++) {
if(ss[j] == '0') p = p->lson;
else p = p->rson;
}
p->val = min(p->val, val);
}
else {
node *p = rootB;
int len = strlen(ss);
for(int j = len-1; j >= 0; j--) {
if(ss[j] == '0') p = p->lson;
else p = p->rson;
}
p->val = min(p->val, val);
}
}
DFS(rootA, 0);
DFS(rootB, 1);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= 8; j++) {
b[j] = a[i] % 2;
a[i] /= 2;
}
int t1, t2;
node *p = rootA;
for(int j = 8; j >= 1; j--) {
if(b[j]) p = p->rson;
else p = p->lson;
}
t1 = p->id;
p = rootB;
for(int j = 1; j <= 8; j++) {
if(b[j]) p = p->rson;
else p = p->lson;
}
t2 = p->id;
addedges(t1, t2, INF);
}
int ans = isap();
if(ans >= INF) printf("-1\n");
else printf("%d\n", ans);
}
int main()
{
_ini();
int _;
scanf("%d", &_);
for(int i = 1; i <= _; i++) {
init();
printf("Case #%d: ", i);
work();
}
return 0;
}