题意
给定一些插头设备和插座,有一些方法可以把其中一些插头变成另一种插头。求无法匹配插座的插头设备个数。
题解
用\(map\)给每个字符串标号为\(a_i\)和\(b_i\)。
读入每种改变插头的方法,连边,权值为\(inf\)。
然后连边\(S \longrightarrow a_i\),权值为\(1\);\(b_i \longrightarrow T\),权值为\(1\)。
跑最大流即可。
代码
#include <bits/stdc++.h>
#define FOPI freopen("in.txt", "r", stdin)
#define FOPO freopen("out.txt", "w", stdout)
#define FOR(i,x,y) for (int i = x; i <= y; i++)
#define ROF(i,x,y) for (int i = x; i >= y; i--)
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int maxn = 1e5 + 100;
const int maxm = 2e5 + 100;
struct Edge
{
int to, next, cap, flow;
}edge[maxm];
int tot;
int head[maxn];
void init()
{
tot = 2;
memset(head, -1, sizeof(head));
}
void build(int u, int v, int w, int rw = 0)
{
edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = 0;
edge[tot].next = head[u]; head[u] = tot++;
edge[tot].to = u; edge[tot].cap = 0; edge[tot].flow = 0;
edge[tot].next = head[v]; head[v] = tot++;
}
int Q[maxn];
int dep[maxn], cur[maxn], sta[maxn];
bool bfs(int s, int t, int n)
{
int front = 0, tail = 0;
memset(dep, -1, sizeof(dep[0]) * (n+1));
dep[s] = 0;
Q[tail++] = s;
while(front < tail)
{
int u = Q[front++];
for (int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if (edge[i].cap > edge[i].flow && dep[v] == -1)
{
dep[v] = dep[u] + 1;
if (v == t) return true;
Q[tail++] = v;
}
}
}
return false;
}
LL dinic(int s, int t, int n)
{
LL maxflow = 0;
while(bfs(s, t, n))
{
for (int i = 0; i < n; i++) cur[i] = head[i];
int u = s, tail = 0;
while(cur[s] != -1)
{
if (u == t)
{
int tp = inf;
for (int i = tail-1; i >= 0; i--)
tp = min(tp, edge[sta[i]].cap - edge[sta[i]].flow);
//if (tp >= inf) return -1;
maxflow += tp;
for (int i = tail-1; i >= 0; i--)
{
edge[sta[i]].flow += tp;
edge[sta[i]^1].flow -= tp;
if (edge[sta[i]].cap - edge[sta[i]].flow == 0) tail = i;
}
u = edge[sta[tail]^1].to;
}
else if (cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow
&& dep[u]+1 == dep[edge[cur[u]].to])
{
sta[tail++] = cur[u];
u = edge[cur[u]].to;
}
else
{
while(u != s && cur[u] == -1) u = edge[sta[--tail]^1].to;
cur[u] = edge[cur[u]].next;
}
}
}
return maxflow;
}
int t;
int a[205], b[205];
string s, r;
map<string, int> M;
int n, m, S, T, cnt, q;
int getid(string &s)
{
if (M.count(s)) return M[s];
return M[s] = ++cnt;
}
int main()
{
// FOPI;
// FOPO;
ios::sync_with_stdio(false);
cin.tie(NULL);
cin >> t;
FOR(ca, 1, t)
{
init();
M.clear(); cnt = 0;
cin >> n;
FOR(i, 1, n) { cin >> s; a[i] = getid(s); }
cin >> m;
FOR(i, 1, m) { cin >> r >> s; b[i] = getid(s); }
cin >> q;
FOR(i, 1, q)
{
cin >> s >> r;
int x = getid(s), y = getid(r);
build(y, x, inf);
}
S = 0, T = cnt+1;
FOR(i, 1, n) build(S, a[i], 1);
FOR(j, 1, m) build(b[j], T, 1);
LL ans = dinic(S, T, T);
printf("%lld\n", m-ans);
if (ca != t) puts("");
}
}