POJ 2771 Guardian of Decency(二分图最大独立集,裸题)

62 篇文章 0 订阅

二分图最大独立集,裸题
题目意思:
有k 个学生,学生有男女,某些男女之间有些可能谈恋爱。老师要带一些学生出去
旅游,要求不能有男女之间谈恋爱。
本题要点:
1、k <= 500, 用邻接矩阵来存图。
左部节点: n个男学生
右部节点: m个女学生。
2、老师要带尽可能多的学生出去,就是取的点尽量多,显然是二分图最大独立集。
二分图最大独立集 = 顶点个数 - 二分图最大匹配

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;
const int MaxN = 510, MaxLen = 110;
int a[MaxN][MaxN], match[MaxN];
bool vis[MaxN];
int T, n, m, k;

struct stu
{
	int h;
	char sex[2], music[MaxLen], sport[MaxLen];
}boys[MaxN], girls[MaxN];

bool dfs(int x)
{
	for(int y = 1; y <= m; ++y)
	{
		if(!a[x][y] || vis[y])
			continue;
		vis[y] = true;
		if(!match[y] || dfs(match[y]))
		{
			match[y] = x;
			return true;
		}
	}
	return false;
}

void solve()
{
	for(int i = 1; i <= n; ++i)
	{
		for(int j = 1; j <= m; ++j)
		{
			if(abs(boys[i].h - girls[j].h) > 40 || strcmp(boys[i].music, girls[j].music) != 0
					|| strcmp(boys[i].sport, girls[j].sport) == 0)
			{
				a[i][j] = 0;		
			}else{
				a[i][j] = 1;
			}
		}
	}
	int ans = 0;
	for(int i = 1; i <= n; ++i)
	{
		memset(vis, false, sizeof vis);
		if(dfs(i))
			++ans;
	}
	printf("%d\n", n + m - ans);
}

int main()
{
	int height;
	char ch[2];
	scanf("%d", &T);
	while(T--)
	{
		memset(a, 0, sizeof a);
		memset(match, 0, sizeof match);
		n = m = 0;
		scanf("%d", &k);
		while(k--)
		{
			scanf("%d%s", &height, ch);	
			if(ch[0] == 'M')
			{
				boys[++n].h = height;
				strcpy(boys[n].sex, ch);
				scanf("%s%s", boys[n].music, boys[n].sport);
			}else{
				girls[++m].h = height;	
				strcpy(girls[m].sex, ch);
				scanf("%s%s", girls[m].music, girls[m].sport);
			}
		}
		solve();
	}
	return 0;
}

/*
2
4
35 M classicism programming
0 M baroque skiing
43 M baroque chess
30 F baroque soccer
8
27 M romance programming
194 F baroque programming
67 M baroque ping-pong
51 M classicism programming
80 M classicism Paintball
35 M baroque ping-pong
39 F romance ping-pong
110 M romance Paintball
*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值