A Plug for UNIX
题意:
房间里有n个不同的插口,有m个设备,每个设备对应一种插口。有k个插口转换器(a, b:表示该转换器可以将插口b转为a),转换器可以插在对应的初始的n个插口,也可以插在对应的转换器上。要使得设备匹配插口最大,求未能匹配的设备数量。(转换器的数量无限)
思路:
如果一个设备对应的插口x可以由转换器级联得到,那么该设备实际上是对应了所有和x在一个网络中的插口。
所以我们根据所有k组转换器信息做成一个有向图(由a指向b),这样的话我们从每个设备对应的插口进行深搜,即可得到设备对应的所有直接或者间接可行插口。
然后每个设备就有了对应的可行插口,再和已有的n个插口进行二分图最大匹配就可以得到最后的答案。
Code:
#include <iostream>
#include <cstdio>
#include <set>
#include <map>
#include <cstring>
#include <string>
using namespace std;
int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -f; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
return x * f;
}
const int maxN = 305;
int n, m, k, has[maxN];
string havePlug[maxN];
string needPlug[maxN];
struct Change{
string to, from;
}change[maxN];
int nodeTot;
map<string, int>number;
int head[maxN], cnt;
struct EDGE{
int adj, to;
EDGE(int a = -1, int b = 0): adj(a), to(b) {}
}edge[maxN];
void add_edge(int u, int v)
{
edge[cnt] = EDGE(head[u], v);
head[u] = cnt ++ ;
}
bool match[maxN][maxN];
int used[maxN], l[maxN];
void init() { for(int i = 1; i <= nodeTot; ++ i ) used[i] = has[i]; }
void getMatch(int u, int x)
{
match[x][u] = true;
for(int i = head[u]; ~i; i = edge[i].adj ) {
int v = edge[i].to;
getMatch(v, x);
}
}
bool Hungary(int x)
{
for(int j = 1; j <= nodeTot; ++ j ) {
if(match[x][j] && used[j]) {
-- used[j];
if(l[j] == 0 || Hungary(l[j])) {
l[j] = x;
return true;
}
}
}
return false;
}
int main()
{
n = read();
for(int i = 1; i <= n; ++ i ) {
cin >> havePlug[i];
if(!number[havePlug[i]]) number[havePlug[i]] = ++ nodeTot;
}
m = read();
for(int i = 1; i <= m; ++ i ) {
string device;
cin >> device >> needPlug[i];
if(!number[needPlug[i]]) number[needPlug[i]] = ++ nodeTot;
}
k = read();
for(int i = 1; i <= k; ++ i ) {
cin >> change[i].to >> change[i].from;
if(!number[change[i].to]) number[change[i].to] = ++ nodeTot;
if(!number[change[i].from]) number[change[i].from] = ++ nodeTot;
}
memset(head, -1, sizeof(head));
for(int i = 1; i <= k; ++ i ) {
int u = number[change[i].to], v = number[change[i].from];
add_edge(u, v);
}
for(int i = 1; i <= m; ++ i ) {
getMatch(number[needPlug[i]], i);
}
for(int i = 1; i <= n; ++ i ) {
++ has[number[havePlug[i]]];
}
int ans = m;
for(int i = 1; i <= m; ++ i ) {
init();
if(Hungary(i)) -- ans;
}
cout << ans << endl;
return 0;
}