marrige problem

// Project 1
// Design and Analysis of Algorithms CSCI-335
// Yu Zhiqiang 2013.11.20

#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <string>
#include <vector>
#include <set>
using namespace std;

const int MAXN = 1024;

int n;                // X 的大小
int weight[MAXN][MAXN];        // X 到 Y 的映射(权重)
int lx[MAXN], ly[MAXN];        // 标号
bool sx[MAXN], sy[MAXN];    // 是否被搜索过
int match[MAXN];        // Y(i) 与 X(match [i]) 匹配
map<string, int> name_to_id;
vector<string> id_to_name;
set<int> boy;

bool path(int u) {
	sx[u] = true;
	for (int v = 0; v < n; v++)
		if (!sy[v] && lx[u] + ly[v] == weight[u][v]) {
			sy[v] = true;
			if (match[v] == -1 || path(match[v])) {
				match[v] = u;
				return true;
			}
		}
	return false;
}

int bestmatch() {
	int i, j;

	// 初始化标号
	for (i = 0; i < n; i++) {
		lx[i] = -0x1FFFFFFF;
		ly[i] = 0;
		for (j = 0; j < n; j++)
			if (lx[i] < weight[i][j])
				lx[i] = weight[i][j];
	}

	memset(match, -1, sizeof(match));
	for (int u = 0; u < n; u++)
		while (1) {
			memset(sx, 0, sizeof(sx));
			memset(sy, 0, sizeof(sy));
			if (path(u))
				break;

			// 修改标号
			int dx = 0x7FFFFFFF;
			for (i = 0; i < n; i++)
				if (sx[i])
					for (j = 0; j < n; j++)
						if (!sy[j])
							dx = min(lx[i] + ly[j] - weight[i][j], dx);
			for (i = 0; i < n; i++) {
				if (sx[i])
					lx[i] -= dx;
				if (sy[i])
					ly[i] += dx;
			}
		}

	int sum = 0;
	for (i = 0; i < n; i++)
		sum += weight[match[i]][i];

	return sum;
}

inline int get_id(string name) {
	if (name_to_id.find(name) == name_to_id.end()) {
		int new_id = name_to_id.size();
		name_to_id[name] = new_id;
		id_to_name.push_back(name);
		return new_id;
	} else {
		return name_to_id[name];
	}
}

inline string get_name(int id) {
	return id_to_name[id];
}

void init() {
	for(int i=0; i<MAXN; i++) {
			for(int j=0; j<MAXN;j++) {
				weight[i][j] = -1e5;
			}
		}
	string name1, name2;
	int w;
	while (cin >> name1 >> name2 >> w and w) {
		int id1 = get_id(name1);
		int id2 = get_id(name2);
		boy.insert(id1);
		cerr << id1 << " " << id2 << endl;
		weight[id1][id2] = w;
		weight[id2][id1] = w;
	}
	n = name_to_id.size();
}

int main() {
	init();
	cout << bestmatch()/2 << endl;
	int sum=0;
	for (int i = 0; i < n; i++)
		if(boy.find(i) != boy.end()) {
			sum += weight[i][match[i]];
			cerr << weight[i][match[i]] << " " << get_name(i) << " -> " << get_name(match[i]) << endl;
		}
	cout << sum << endl;
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值