zoj 1157 A Plug for UNIX

很显然 插头与插座之间的关系符合二分图
所以老样子,先建图,后匈牙利
因为有插头转接器
所以这题的建图需要先计算出来某个插头可以到的所有插座
然后在进行建图

#include<iostream>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<vector>
#include<set>
#include<queue>
#include<list>
#include<map>
using namespace std;
const int maxi = 110;

int mp[maxi][maxi], used[maxi], who[maxi];
map<string, vector<string> > drec;
map<string, vector<string> > oriDrec;
map<string, int> rece_to_id;
map<string, string> device_to_plug;
map<string, int> device_to_index;
string device[maxi];
string rece[maxi];
int n, m;
void inti() {
	memset(mp, 0, sizeof(mp));
	memset(used, 0, sizeof(used));
	memset(who, 0, sizeof(who));
	drec.clear();
	oriDrec.clear();
	rece_to_id.clear();
	device_to_index.clear();
	device_to_plug.clear();
}

void trackback(string ori) {
	vector<string> v = drec[ori];
	set<string> add;
	for (int i = 0; i < v.size(); i++) {
		if (drec.find(v[i]) != drec.end()) {
			vector<string> t = drec[v[i]];
			for (int j = 0; j < t.size(); j++) {
				if (find(v.begin(), v.end(), t[j]) == v.end()) {//若是原先v中没有的方向,则将其加入
					add.insert(t[j]);
				}
			}
		}
	}

	if (add.size() != 0) {
		for (set<string>::iterator it = add.begin(); it != add.end(); it++) {
			v.push_back(*it);
		}
		drec[ori] = v;
		vector<string> par = oriDrec[ori];
		for (int i = 0; i < par.size(); i++) {
			trackback(par[i]);
		}
	}
}

void getDre() {
	map<string, vector<string>>::iterator it;
	for (it = drec.begin(); it != drec.end(); it++) {
		trackback(it->first);
	}
}

void read() {
	cin >> n;
	string str, plug;
	for (int i = 1; i <= n; i++) {
		cin >> str;
		rece[i] = str;
		rece_to_id[str] = i;
	}
	cin >> m;
	for (int i = 1; i <= m; i++) {
		cin >> str >> plug;
		device_to_plug[str] = plug;
		device_to_index[str] = i;
		device[i] = str;
	}
	int t;
	cin >> t;
	string from, to;
	for (int i = 0; i < t; i++) {
		cin >> from >> to;
		vector<string> tos = drec[from];
		tos.push_back(to);
		drec[from] = tos;
		vector<string> froms = oriDrec[to];
		froms.push_back(from);
		oriDrec[to] = froms;
	}

	for (map<string, vector<string>>::iterator it = drec.begin(); it != drec.end(); it++) {
		vector<string> t = it->second;
		t.push_back(it->first);
		it->second = t;
	}
}

void build() {
	for (int i = 1; i <= m; i++) {
		string str = device[i];
		string plug = device_to_plug[str];
		if(rece_to_id.find(plug)!=rece_to_id.end()){
			mp[i][rece_to_id[plug]]=1;
		}
		vector<string> plug_to = drec[plug];
		for (int j = 0; j < plug_to.size(); j++) {
			if (rece_to_id.find(plug_to[j]) != rece_to_id.end()) {
				mp[i][rece_to_id[plug_to[j]]] = 1;
			}
		}
	}
}

int dfs(int u) {
	for (int i = 1; i <= n; i++) {
		if (mp[u][i] && !used[i]) {
			used[i] = 1;
			if (!who[i] || dfs(who[i])) {
				who[i] = u;
				return 1;
			}
		}
	}
	return 0;
}

int hungry() {
	int all = 0;
	for (int i = 1; i <= m; i++) {
		memset(used, 0, sizeof(used));
		if (dfs(i))all++;
	}
	return all;
}

void solve() {
	
//	for(int i=1;i<=m;i++){
//		cout << "name:"<<device[i]<<" ";
//		for(int j=1;j<=n;j++){
//			if(mp[i][j])cout << rece[j]<<" ";
//		}
//		cout << endl;
//	}
	
	int mat = hungry();
//	cout << mat << endl;
	cout << m - mat << endl;
}

int main() {
	int t;
	cin >> t;
	while (t--) {
		inti();
		read();
		getDre();
		build();
		solve();
		if(t) cout << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值