题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=0&problem=694&mosmsg=Submission+received+with+ID+26555189
将所有插头类型看成点,从源点向设备连边,容量为 \(1\), 从插座向汇点连边,容量为 \(1\),转换器的插头间连边,容量为 \(INF\)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 405;
const int INF = 1000000007;
int T, n, N, M, K, ans;
int target[maxn], device[maxn], from[maxn], to[maxn];
vector<string> names;
int ID(const string s){
for(int i = 0 ; i < names.size() ; i++){
if(names[i] == s) return (i + 1);
}
names.push_back(s);
return names.size();
}
int h[maxn], cnt = 1;
struct Edge{
int from, to, cap, flow, next;
}e[(maxn * maxn)<< 1];
void add(int u, int v, int c){
e[++cnt].to = v;
e[cnt].cap = c;
e[cnt].next = h[u];
h[u] = cnt;
}
int d[maxn];
queue<int> q;
int s, t;
int bfs(){
while(!q.empty()) q.pop();
memset(d,0,sizeof(d));
d[s] = 1;
q.push(s);
while(!q.empty()){
int u = q.front(); q.pop();
for(int i = h[u] ; i != -1 ; i = e[i].next){
int v = e[i].to;
if(!d[v] && e[i].cap){
d[v] = d[u] + 1;
q.push(v);
}
}
}
return d[t];
}
int dfs(int u,int lim){
if(u==t) return lim;
int f=0,tmp;
for(int i=h[u];i!=-1;i=e[i].next){
int v=e[i].to;
if(d[v]==d[u]+1&&e[i].cap&&(tmp=dfs(v,min(lim,e[i].cap)))){
e[i].cap-=tmp; e[i^1].cap+=tmp;
f+=tmp; lim-=tmp;
if(!lim) return f;
}
}
if(lim) d[u]=0;
return f;
}
void dinic(){
ans=0;
while(bfs()){
ans+=dfs(s,INF);
}
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
cin >> T;
int flag = 0;
while(T--){
if(flag) printf("\n");
flag = 1;
ans = 0;
names.clear();
memset(d, 0, sizeof(d));
memset(h, -1, sizeof(h));
cnt = 1;
string s1, s2;
cin >> N;
for(int i = 1 ; i <= N ; ++i){
cin >> s1;
target[i] = ID(s1);
}
cin >> M;
for(int i = 1 ; i <= M ; ++i){
cin >> s1 >> s2;
device[i] = ID(s2);
}
cin >> K;
for(int i = 1 ; i <= K ; ++i){
cin >> s1 >> s2;
from[i] = ID(s1);
to[i] = ID(s2);
}
n = names.size();
for(int i = 1 ; i <= M ; ++i){ // 源点 -> 设备
add(n + 1, device[i], 1);
add(device[i], n + 1, 0);
}
for(int i = 1 ; i <= N ; ++i){ // 插座 -> 汇点
add(target[i], n + 2, 1);
add(n + 2, target[i], 0);
}
for(int i = 1 ; i <= K ; ++i){ // 插头 -> 插头
add(from[i], to[i], INF);
add(to[i], from[i], 0);
}
s = n + 1, t = n + 2;
dinic();
printf("%d\n", M - ans);
}
return 0;
}