根据关系建一个图,然后就是后面的插座的传递闭包,一个floyd构边。
代码如下:
#include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <map> #include <string> #define INF 0x3fffffff #define CN(x) (255+(x)) #define MN(x) (555+(x)) #define MAXN 500 using namespace std; int N, M, K, rec[MAXN], idx, cnt; int head[1000], dis[1000], que[1000], front, tail; const int SS = 0, TT = 998; bool R[505][505]; map<string,int>mp; struct Edge { int v, cap, next; }e[500000]; void addedge(int a, int b, int cap) { ++idx; e[idx].v = b, e[idx].cap = cap; e[idx].next = head[a], head[a] = idx; ++idx; e[idx].v = a, e[idx].cap = 0; e[idx].next = head[b], head[b] = idx; } bool bfs() { int pos; memset(dis, 0xff, sizeof (dis)); dis[SS] = front = tail = 0; que[++tail] = SS; while (front != tail) { pos = que[++front]; for (int i = head[pos]; i != -1; i = e[i].next) { if (e[i].cap > 0 && dis[e[i].v] == -1) { dis[e[i].v] = dis[pos] + 1; if (e[i].v == TT) return true; que[++tail] = e[i].v; } } } return false; } int dfs(int u, int flow) { if (u == TT) { return flow; } int f, tf = 0; for (int i = head[u]; i != -1; i = e[i].next) { if (dis[u]+1 == dis[e[i].v] && e[i].cap > 0 && (f = dfs(e[i].v, min(e[i].cap, flow-tf)))) { e[i].cap -= f, e[i^1].cap += f; tf += f; if (tf == flow) return flow; } } if (!tf) dis[u] = -1; return tf; } int dinic() { int ret = 0; while (bfs()) { ret += dfs(SS, INF); } return ret; } void floyd() { for (int k = 1; k <= cnt; ++k) { for (int i = 1; i <= cnt; ++i) { for (int j = 1; j <= cnt; ++j) { R[i][j] |= R[i][k] & R[k][j]; } } } } int main() { char name[30], str[30]; while (scanf("%d", &N) == 1) { cnt = 0; idx = -1; memset(rec, 0, sizeof (rec)); memset(head, 0xff, sizeof (head)); memset(R, 0, sizeof (R)); mp.clear(); for (int i = 1; i <= N; ++i) { scanf("%s", name); if (!mp.count(name)) { mp[name] = ++cnt; } ++rec[mp[name]]; // 将插座的信息统计好 } scanf("%d", &M); for (int i = 1; i <= M; ++i) { scanf("%s %s", str, name); if (!mp.count(name)) { mp[name] = ++cnt; } addedge(SS, i, 1); addedge(i, CN(mp[name]), 1); } for (int i = 1; i <= cnt; ++i) { addedge(CN(i), MN(i), rec[i]); addedge(MN(i), TT, INF); } scanf("%d", &K); for (int i = 1; i <= K; ++i) { scanf("%s %s", str, name); if (!mp.count(str)) mp[str] = ++cnt; if (!mp.count(name)) mp[name] = ++cnt; R[mp[str]][mp[name]] = true; } floyd(); for (int i = 1; i <= cnt; ++i) { for (int j = 1; j <= cnt; ++j) { if (R[i][j]) { addedge(CN(i), CN(j), INF); } } } printf("%d\n", M-dinic()); } return 0; }