其实网络流的题目习惯之后建图还是挺容易的。
习惯,好深奥啊。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
const int INF = 1 << 20;
const int MaxN = 1005;
struct NetWork
{
struct Adj
{
int v, c, b;
Adj() {}
Adj(int _v, int _c, int _b) : v(_v), c(_c), b(_b) {}
};
int n, s, t, h[MaxN], cnt[MaxN];
vector<Adj> adj[MaxN];
void clear()
{
for(int i = 0; i < n; i++) {
adj[i].clear();
}
n = 0;
}
void add_edge(int u, int v, int c)
{
n = max( n, max(u, v) + 1 );
adj[u].push_back(Adj(v, c, adj[v].size()));
adj[v].push_back(Adj(u, 0, adj[u].size() - 1));
}
int max_flow(int _s, int _t)
{
s = _s, t = _t;
fill(h, h + n, 0);
fill(cnt, cnt + n, 0);
int flow = 0;
while(h[s] < n) {
flow += dfs(s, INF);
}
return flow;
}
int dfs(int u, int flow)
{
if(u == t) return flow;
int minh = n - 1, ct = 0;
for(vector<Adj>::iterator it = adj[u].begin(); flow && it != adj[u].end(); it++) {
if(it->c) {
if(h[it->v] + 1 == h[u]) {
int k = dfs(it->v, min(it->c, flow));
if(k) {
it->c -= k;
adj[it->v][it->b].c += k;
flow -= k;
ct += k;
}
if(h[s] >= n) return ct;
}
minh = min(minh, h[it->v]);
}
}
if(ct) return ct;
if(--cnt[ h[u] ] == 0) h[s] = n;
h[u] = minh + 1;
++cnt[h[u]];
return 0;
}
}network;
int n, m, k;
map<string, int> id1, id2;
int total1, total2;
map<int, int> mp;
int main()
{
while(1 == scanf("%d", &n)) {
id1.clear();
total1 = 0;
for(int i = 1; i <= n; i++) {
string s;
cin >> s;
if(id1[s] == 0) id1[s] = ++total1;
}
int id = total1;
scanf("%d", &m);
id2.clear();
total2 = 0;
mp.clear();
for(int i = 0; i < m; i++) {
string s1, s2;
cin >> s1 >> s2;
if(id2[s1] == 0) id2[s1] = ++total2;
if(id1[s2] == 0) id1[s2] = ++total1;
mp[id2[s1]] = id1[s2];
}
int s = 0;
network.clear();
for(int i = 1; i <= total2; i++) {
network.add_edge(s, i, 1);
}
for(map<int, int>::iterator it = mp.begin(); it != mp.end(); it++) {
network.add_edge(it->first, it->second + total2, 1);
}
scanf("%d", &k);
for(int i = 0; i < k; i++) {
string s1, s2;
cin >> s1 >> s2;
if(id1[s1] == 0) id1[s1] = ++total1;
if(id1[s2] == 0) id1[s2] = ++total1;
network.add_edge(id1[s1] + total2, id1[s2] + total2, INF);
}
int t = total1 + total2 + 1;
for(int i = 1; i <= id; i++) {
network.add_edge(total2 + i, t, 1);
}
int res = network.max_flow(s, t);
printf("%d\n", m - res);
}
return 0;
}