题意
传送门 POJ 1087
题解
使用 m a p map map 维护接口类型。 F l o y d − W a r s h a l l Floyd-Warshall Floyd−Warshall 判连通性,以判断设备的接口与插座的接口是否可以匹配。设备向其接口可匹配的插座连边,跑最大二分匹配即可,实现上使用匈牙利算法。
考虑到插头、插座与适配器都有可能出现新的接口类型,故 F l o y d − W a r s h a l l Floyd-Warshall Floyd−Warshall 节点最大数量 m a x n maxn maxn 应该为 400 400 400。
#include <algorithm>
#include <cstring>
#include <iostream>
#include <map>
#include <string>
#include <vector>
using namespace std;
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define MAX_V 405
int V;
vector<int> G[MAX_V];
int match[MAX_V];
bool used[MAX_V];
void add_edge(int u, int v)
{
G[u].push_back(v);
G[v].push_back(u);
}
bool dfs(int v)
{
used[v] = true;
for (int i = 0; i < G[v].size(); i++)
{
int u = G[v][i], w = match[u];
if (w < 0 || (!used[w] && dfs(w)))
{
match[v] = u;
match[u] = v;
return true;
}
}
return false;
}
int bipartite_matching()
{
int res = 0;
memset(match, -1, sizeof(match));
for (int v = 0; v < V; v++)
{
if (match[v] < 0)
{
memset(used, 0, sizeof(used));
if (dfs(v))
{
++res;
}
}
}
return res;
}
#define maxn 405
int n, m, k, nr;
int dv[maxn], dp[maxn][maxn];
map<string, int> mpr;
void floyd_warshall(int n)
{
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
dp[i][j] |= (dp[i][k] & dp[k][j]);
}
}
}
}
int main()
{
string sr, sd;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> sr;
if (mpr.find(sr) == mpr.end()) mpr[sr] = nr++;
}
cin >> m;
int nr2 = nr;
for (int i = 0; i < m; i++)
{
cin >> sd >> sr;
if (mpr.find(sr) == mpr.end()) mpr[sr] = nr2++;
dv[i] = mpr[sr];
}
cin >> k;
for (int i = 0; i < k; i++)
{
cin >> sr >> sd;
if (mpr.find(sr) == mpr.end()) mpr[sr] = nr2++;
if (mpr.find(sd) == mpr.end()) mpr[sd] = nr2++;
dp[mpr[sr]][mpr[sd]] = 1;
}
for (int i = 0; i < nr2; i++) dp[i][i] = 1;
floyd_warshall(nr2);
V = nr + m;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < nr; j++)
{
if (dp[dv[i]][j]) add_edge(i, j + m);
}
}
cout << m - bipartite_matching() << endl;
return 0;
}