题意: 略。
解法: 把插座和源点建边,插座和转换器建边,以需求为边连汇点,求一遍最大流。
在ZOJ诡异的PE之后,果断把set换成手写trie树,还是PE。然后在POJ无压力AC了。对ZOJ表示一下无奈。
trie树写的有点弱,没用指针优化,而且固定空间。
第二发最大流,还是Frod-Fullkerson
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
using namespace std;
const int INF = ~0u>>1;
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define FOR(i,a,b) for(int i=(a); i<=(b); i++)
#define clr(a,b) memset(a,b,sizeof(a))
const int MAXN = 410;
struct ArcType {
int c, f;
};
ArcType g[MAXN][MAXN];
int prev[MAXN];
int alpha[MAXN];
int flag[MAXN];
int que[MAXN];
int tot;
class TRIE {
public:
struct NOD {
int rank;
int c[26];
int C[26];
int nu[10];
}node[10010];
int tp;
void init() {
tp = 0;
New_node();
}
int New_node() {
clr(node[tp].c,-1);
clr(node[tp].C,-1);
clr(node[tp].nu,-1);
node[tp].rank = -1;
return tp ++;
}
int Find(char *s) {
int now = 0;
for(; *s; s++) {
if(isdigit(*s)) {
int a = (*s) - '0';
if(node[now].nu[a] == -1) node[now].nu[a] = New_node();
now = node[now].nu[a];
}
else if(isupper(*s)) {
int a = (*s) - 'A';
if(node[now].C[a] == -1) node[now].C[a] = New_node();
now = node[now].C[a];
}
else {
int a = (*s) - 'a';
if(node[now].c[a] == -1) node[now].c[a] = New_node();
now = node[now].c[a];
}
}
if(node[now].rank < 0) node[now].rank = tot ++;
return node[now].rank;
}
}trie;
int Ford() {
while(1) {
clr(flag,-1);
int qs,qe;
qs = qe = 0;
que[qs] = 0;
alpha[0] = INF;
flag[0] = 0;
while(qs <= qe && flag[1] == -1) {
int v = que[qs++];
REP(i,0,tot) {
if(flag[i] != -1) continue;
if(g[v][i].c > g[v][i].f) {
alpha[i] = min(alpha[v],g[v][i].c-g[v][i].f);
flag[i] = 0; prev[i] = v;
que[++qe] = i;
}
else if(g[i][v].f > 0) {
alpha[i] = min(alpha[v], g[i][v].f);
flag[i] = 0; prev[i] = -v;
que[++qe] = i;
}
}
flag[v] = 1;
}
if(flag[1] == -1 || alpha[1] == 0) break;
int a = alpha[1];
int k1,k2;
k1 = 1;
k2 = abs(prev[k1]);
while(k1 != 0) {
if(g[k2][k1].c > 0) g[k2][k1].f += a;
else g[k1][k2].f -= a;
k1 = k2;
k2 = abs(prev[k1]);
}
}
int ret = 0;
REP(i,0,tot) ret += g[0][i].f;
return ret;
}
int main() {
int cas;
int n;
int num;
char s[2][30];
cas = 1;
while(cas--) {
trie.init();
clr(g,0);
scanf("%d", &n);
tot = 2;
while(n--) {
scanf("%s", s[0]);
int tt = trie.Find(s[0]);
g[0][tt].c ++;
}
scanf("%d", &n);
num = n;
while(n--) {
scanf("%*s%s", s[0]);
int tt = trie.Find(s[0]);
g[tt][1].c ++;
}
scanf("%d", &n);
while(n--) {
scanf("%s%s", s[0],s[1]);
int t0 = trie.Find(s[0]);
int t1 = trie.Find(s[1]);
g[t1][t0].c = INF;
}
printf("%d\n", num - Ford());
}
return 0;
}