codeforces 166D Shoe Store 二分图 匈牙利算法

题意:有n双鞋,给定其分别的售价和尺码,保证所有鞋的尺码是不用的,有m个人来买鞋,给定其脚的大小以及手里的钱,他可以买跟脚号码相等或者大一号的鞋,同时需要保证手里的钱足够,问最多卖出的营业额是多少


因为每双鞋的尺码是不一样的,所以每个人最多有两种购买的可能,一边是顾客,一边是鞋,用map建成二分图,然后用匈牙利求解即可

但是为了保证营业额最大,首先要将鞋的售价降序排序,这样可以保证最优解

用前向星就tle,用vector就过了。。有点迷。。。

#include <iostream>
#include <map>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#define rep(i, j, k) for (int i = j; i <= k; i++)
#define maxn 100009
#define ll long long

using namespace std;

int n, to[maxn * 6], Next[maxn * 6], head[maxn], match[maxn];//, vis[maxn];
int tot = 0;
int m, ret;
ll ans = 0;
vector<int> edge[maxn];

struct cadongllas
{
	int money, size, num;
}a[maxn], b[maxn];

void add (int u, int v)
{
	//to[++tot] = v; Next[tot] = head[u]; head[u] = tot;
	edge[u].push_back (v);
}

bool dfs (int x)
{
	//for (int i = head[x]; i; i = Next[i])
	for (int i = 0; i < edge[x].size (); i++)
		if (match[edge[x][i]] != x)
		{
			if (match[edge[x][i]] == -1 || dfs (match[edge[x][i]]))
			{
				match[edge[x][i]] = x;
				return 1;
			}
		}
	return 0;
}

bool cmp (cadongllas x, cadongllas y)
{
	return x.money > y.money;
}

int main ()
{
	map <int, int> num;
	cin >> n;
	rep (i, 1, n)
		scanf ("%d%d", &a[i].money, &a[i].size), a[i].num = i;
	sort (a + 1, a + 1 + n, cmp);
	cin >> m;
	rep (i, 1, m)
		scanf ("%d%d", &b[i].money, &b[i].size);
	rep (i, 1, n)
		num[a[i].size] = i;
	rep (i, 1, m)
	{
		if (num[ b[i].size + 1] && b[i].money >= a[ num[ b[i].size + 1]].money)
			add (num[ b[i].size + 1], i);
		if (num[b[i].size] && b[i].money >= a[ num[b[i].size]].money)
			add (num[b[i].size], i);
	}
	memset (match, -1, sizeof (match));
	rep (i, 1, n)
	{
		//memset (vis, 0, sizeof (vis));
		if (dfs (i))
		{
			ans += a[i].money * 1LL;
			ret++;
		}
	}
	cout << ans << endl << ret << endl;
	rep (i, 1, m)
		if (match[i] != -1)
			printf ("%d %d\n", i, a[match[i]].num);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值