jzojP2071 座位安排(二分图最大匹配)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhanghaoxian1/article/details/83513464

P2071 座位安排

题目背景
公元二零一四年四月十七日,小明参加了省赛,在一路上,他遇到了许多问题,请你帮他解决。

题目描述
已知车上有N排座位,有N*2个人参加省赛,每排座位只能坐两人,且每个人都有自己想坐的排数,问最多使多少人坐到自己想坐的位置。

输入输出格式
输入格式:
第一行,一个正整数N。
第二行至第N*2+1行,每行两个正整数Si1,Si2,为每个人想坐的排数。

输出格式:
一个非负整数,为最多使得多少人满意。

输入输出样例
输入样例#1:
4
1 2
1 3
1 2
1 3
1 3
2 4
1 3
2 3
输出样例#1:
7
说明
对于10%的数据 N≤10
对于30%的数据 N≤50
对于60%的数据 N≤200
对于100%的数据 N≤2000
算法提示:二分图的最大匹配

分析:模板题,给link数组多加一维即可。

代码

#include <cstdio>
#include <string>
#include <cstring>
#define N 50000
using namespace std;

struct arr
{
	int to, nxt;
}a[N];



int n,m,ls[N],link[N][3],l;
bool v[N];

void add(int x, int y)
{
	a[++l].to = y;
	a[l].nxt = ls[x];
	ls[x] = l;
}

bool find(int x)
{
	for (int i = ls[x]; i; i = a[i].nxt)
		if (!v[a[i].to])
		{
			v[a[i].to] = true;
			if (!link[a[i].to][1] || find(link[a[i].to][1])) 
			{
				link[a[i].to][1] = x;
				return true;
			}
			if (!link[a[i].to][2] || find(link[a[i].to][2])) 
			{
				link[a[i].to][2] = x;
				return true;
			}
		}
	return false;
}

int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n * 2; i++)
	{
		int x, y;
		scanf("%d%d", &x, &y);
		add(i, x); 
		add(i, y);
	}
	int ans = 0;
	for (int i = 1; i <= n * 2; i++)
	{
		memset(v, false, sizeof(v));
		if (find(i)) ans++;
	}
	printf("%d\n", ans);
}

猜你喜欢

转载自blog.csdn.net/zhanghaoxian1/article/details/83513464