构图很直接.
坑:样例之间的空行,转换器之间的对接,转换器有无限多个所以和转换器有关的容量都是无穷.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define INF 11111111
#define maxn 311
#define maxm 2111111
int n, m, k;
int s, t;
char s1[maxn][maxn], s2[maxn][maxn], s3[2][maxn][maxn];
struct Edge
{
int to,next,cap,flow;
void get(int a,int b,int c,int d)
{
to=a;next=b;cap=c;flow=d;
}
}edge[maxm];
int tol;
int head[maxn];
int gap[maxn],dep[maxn],pre[maxn],cur[maxn];
void init()
{
tol=0;
memset(head,-1,sizeof(head));
}
void add_edge(int u,int v,int w,int rw=0)
{
edge[tol].get(v,head[u],w,0);head[u]=tol++;
edge[tol].get(u,head[v],rw,0);head[v]=tol++;
}
int sap(int start,int end,int N)
{
memset(gap,0,sizeof(gap));
memset(dep,0,sizeof(dep));
memcpy(cur,head,sizeof(head));
int u=start;
pre[u]=-1;
gap[0]=N;
int ans=0;
while(dep[start]<N)
{
if(u==end)
{
int Min=INF;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
if(Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
{
edge[i].flow+=Min;
edge[i^1].flow-=Min;
}
u = start;
ans+=Min;
continue;
}
bool flag=false;
int v;
for(int i=cur[u];i !=-1;i=edge[i].next)
{
v=edge[i].to;
if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u])
{
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag)
{
u=v;
continue;
}
int Min=N;
for(int i=head[u];i!=-1;i=edge[i].next)
if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min)
{
Min=dep[edge[i].to];
cur[u]=i;
}
gap[dep[u]]--;
if(!gap[dep[u]]) return ans;
dep[u]=Min+1;
gap[dep[u]]++;
if(u!=start) u=edge[pre[u]^1].to;
}
return ans;
}
int main () {
//freopen ("in.txt", "r", stdin);
int tt, kase = 0;
scanf ("%d", &tt);
while (tt--) {
if (kase++)
printf ("\n");
scanf ("%d", &n);
for (int i = 1; i <= n; i++) {
scanf ("%s", s1[i]);
}
scanf ("%d", &m);
for (int i = 1; i <= m; i++) {
scanf ("%s%s", s2[i], s2[i]);
}
scanf ("%d", &k);
for (int i = 1; i <= k; i++) {
scanf ("%s%s", s3[0][i], s3[1][i]);
}
s = 0, t = n+m+k+1;
init ();
for (int i = 1; i <= n; i++) {
add_edge (i, t, 1);
add_edge (t, i, 0);
}
for (int i = n+1; i <= n+m; i++) {
add_edge (0, i, 1);
add_edge (i, 0, 0);
}
for (int i = n+m+1; i <= n+m+k; i++) {
for (int j = 1; j <= n; j++) {
if (strcmp (s3[1][i-n-m], s1[j]) == 0) {
//cout << s3[1][i-n-m] << s1[j] << endl;
add_edge (i, j, 1);
add_edge (j, i, 0);
}
}
for (int j = n+1; j <= n+m; j++) {
if (strcmp (s3[0][i-n-m], s2[j-n]) == 0) {
add_edge (j, i, 1);
add_edge (i, j, 0);
}
}
for (int j = n+m+1; j <= n+m+k; j++) {
if (i == j)
continue;
if (strcmp (s3[1][i-n-m], s3[0][j-n-m]) == 0) {//cout << "//" << endl;
add_edge (i, j, 1);
add_edge (j, i, 0);
}
}
}
for (int i = n+1; i <= n+m; i++) {
for (int j = 1; j <= n; j++) {
if (strcmp (s2[i-n], s1[j]) == 0) {
add_edge (i, j, 1);
add_edge (j, i, 0);
}
}
}
int ans = sap (s, t, n+m+k+2);
//cout << ans << endl;
printf ("%lld\n", (long long)m-ans);
}
return 0;
}