题意:n个插座,m个设备及其插头类型,k种转换器,没有转换器的情况下插头只能插到类型名称相同的插座中,问最少剩几个不匹配的设备
lrj紫书里面讲得挺好的。
先跑一遍floyd,看看插头类型a能否转换为b
然后构造网络
源点为0, 汇点为n + m + 1,源点连插头 容量为1,插座连汇点,容量为1
插头和插座能互相转换的容量为INF,跑一遍最大流 m - 最大流就是答案
顺便粘一下dinic的板子
#include <bits/stdc++.h>
using namespace std; inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar();}
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar();}
return x * f;
} const int N = ;
const int INF = 0x3f3f3f3f;
int n, m, k, tol, cnt;
map<string, int> mp;
vector<int> a;
vector<int> b;
bool f[N][N];
struct Edge { int v, f, next; } edge[N * ];
int head[N], level[N], iter[N]; inline void init() {
mp.clear();
a.clear();
b.clear();
tol = cnt = ;
memset(f, , sizeof(f));
memset(head, -, sizeof(head));
} inline void addedge(int u, int v, int f) {
edge[cnt].v = v; edge[cnt].next = head[u]; edge[cnt].f = f; head[u] = cnt++;
} void floyd() {
for (int k = ; k <= tol; k++) {
for (int i = ; i <= tol; i++) {
for (int j = ; j <= tol; j++) {
f[i][j] = f[i][j] || (f[i][k] && f[k][j]);
}
}
}
} bool bfs(int s, int t) {
for (int i = ; i <= t; i++) iter[i] = head[i], level[i] = -;
level[s] = ;
queue<int> que;
que.push(s);
while (!que.empty()) {
int u = que.front(); que.pop();
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].v, f = edge[i].f;
if (f > && level[v] == -) {
level[v] = level[u] + ;
que.push(v);
}
}
}
return level[t] != -;
} int dfs(int u, int t, int f) {
if (!f || u == t) return f;
int flow = , w;
for (int i = iter[u]; ~i; i = edge[i].next) {
iter[u] = i;
int v = edge[i].v;
if (level[v] == level[u] + && edge[i].f > ) {
w = dfs(v, t, min(f, edge[i].f));
if (w == ) continue;
f -= w;
edge[i].f -= w;
edge[i^].f += w;
flow += w;
if (f <= ) break;
}
}
return flow;
} int dinic(int s, int t) {
int ans = ;
while (bfs(s, t)) ans += dfs(s, t, INF);
return ans;
} int main() {
int T = read();
while (T--) {
init();
n = read();
for (int i = ; i <= n; i++) {
string s;
cin >> s;
mp[s] = i;
a.emplace_back(i);
tol++;
}
m = read();
for (int i = ; i <= m; i++) {
string str1, s;
cin >> str1 >> s;
if (!mp.count(s)) {
mp[s] = ++tol;
}
b.emplace_back(mp[s]);
}
k = read();
for (int i = ; i <= k; i++) {
string s1, s2;
cin >> s1 >> s2;
if (!mp.count(s1)) mp[s1] = ++tol;
if (!mp.count(s2)) mp[s2] = ++tol;
f[mp[s1]][mp[s2]] = ;
}
for (int i = ; i <= tol; i++) f[i][i] = ;
floyd();
for (int i = ; i <= m; i++) {
addedge(, i, );
addedge(i, , );
}
for (int i = ; i <= n; i++) {
addedge(m + i, n + m + , );
addedge(n + m + , m + i, );
}
for (int i = ; i < m; i++) {
for (int j = ; j < n; j++) {
if (!f[b[i]][a[j]]) continue;
addedge(i + , m + j + , INF);
addedge(m + j + , i + , );
}
}
printf("%d\n", m - dinic(, n + m + ));
if (T) puts("");
}
return ;
}