题意:一间房间里面有多重插头,每种类型的插头只有一个,每种设备对应一个插头,部分设备对应的插头没有,但给出了一些不限制数量的插头转换器,求出不能工作的设备的最小数量。
思路:ac的第一道二分图匹配的题。二分图匹配就是特殊的网络流问题,所以用网络流的模板就可以轻松解决。虽然属于入门的网络流,因为构图问题仍然wa掉了两次,还需多练习,代码依然写的太渣。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <map>
#include <set>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAX_V = 300;
struct edge {
int to, cap, rev;
};
vector<edge> G[MAX_V];
bool used[MAX_V];
void add_edge(int from, int to, int cap) {
G[from].push_back((edge){to, cap, G[to].size()});
G[to].push_back((edge){from, 0, G[from].size() - 1});
}
int dfs(int v, int t, int f) {
if(v == t) return f;
used[v] = true;
for(int i = 0; i < G[v].size(); i++) {
edge &e = G[v][i];
if(!used[e.to] && e.cap > 0) {
int d = dfs(e.to, t, min(f, e.cap));
if(d > 0) {
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
int max_flow(int s, int t) {
int flow = 0;
for(;;) {
memset(used, 0, sizeof(used));
int f = dfs(s, t, INF);
if(f > 0) flow += f;
else {
return flow;
}
}
}
set<string> rec;
set<string> dev;
map<string, string> dev_rec;
vector<pair<string, string> > adapters;
map<string, int> rec2id;
map<string, int> dev2id;
map<string, bool> is_exit;
//const int MAX_N = 100 + 5;
int N, M, K;
int main() {
while(cin >> N) {
//initial
for(int i = 0; i < MAX_V; i++) {
G[i].clear();
}
rec.clear();
dev.clear();
dev_rec.clear();
adapters.clear();
rec2id.clear();
dev2id.clear();
is_exit.clear();
//input
for(int i = 0; i < N; i++) {
string receptancle;
cin >> receptancle;
rec.insert(receptancle);
is_exit[receptancle] = true;
}
cin >> M;
for(int i = 0; i < M; i++) {
string device, receptancle;
cin >> device >> receptancle;
dev.insert(device);
rec.insert(receptancle);
dev_rec[device] = receptancle;
}
cin >> K;
for(int i = 0; i < K; i++) {
string rec_in, rec_out;
cin >> rec_in >> rec_out;
rec.insert(rec_in);
rec.insert(rec_out);
adapters.push_back(make_pair(rec_in, rec_out));
}
set<string>::iterator it;
int i = 0;
int n = rec.size(), m = dev.size();
for(it = rec.begin(), i = 0; it != rec.end(); it++, i++) {
rec2id[*it] = i;
}
for(it = dev.begin(), i = 0; it != dev.end(); it++, i++) {
dev2id[*it] = n + i;
}
int s = n + m , t = n + m + 1;
//make graph
for(it = rec.begin(); it != rec.end(); it++) {
if(is_exit[*it])
add_edge(rec2id[*it], t, 1);
}
for(it = dev.begin(); it != dev.end(); it++) {
add_edge(s, dev2id[*it], 1);
}
for(int i = 0; i < adapters.size(); i++) {
add_edge(rec2id[adapters[i].first], rec2id[adapters[i].second], INF);
}
map<string, string>::iterator d_it;
for(d_it = dev_rec.begin(); d_it != dev_rec.end(); d_it++) {
add_edge(dev2id[d_it->first], rec2id[d_it->second], 1);
}
/*DEBUG
cout << "debug:" << n << " " << m << endl;
for(int i = 0; i <= t; i++) {
for(int j = 0; j < G[i].size(); j++) {
cout<< "debug:" << i << " " << G[i][j].to << " " << G[i][j].cap << endl;
}
}
DEBUG*/
int flow = max_flow(s, t);
int ans = M - flow;
cout << ans << endl;
}
return 0;
}