HDU_1068 GirlsandBoys ( 二分图最大匹配/独立集 | 匈牙利算法 )

文章目录


题目连接 vj or hdu

题意

找出一个最大的集合使得该集合的任意两个人没有关系

题解

最大匹配:二分图中边集的数目最大的那个匹配;
最大独立集:在N个点的图G中选出m个点,使这m个点两两之间没有边的点中,m的最大值。

在二分图中, 最大独立集 = 顶点数-最大匹配数

题目没有明确说明些是男的哪些是女的,说明没有明显的二分图,所以将一个人拆成两个人进行最大匹配, 所以多了一倍, 最大匹配数应该是求出来的数除以2

代码

#include <bits/stdc++.h> 
using namespace std; 
#define rg register 
#define sc scanf 
#define pf printf 
typedef long long ll; 


class Hungary {
public:
	static const int MAXN = 1e5+100;
	static const int MAXM = 2e5+10; 
	struct EDGE {
		int v, to;
	}e[MAXM];
	int head[MAXM], cnt = 0;
	inline void add ( int u, int v ) {
		e[cnt].v = v, e[cnt].to = head[u]; head[u] = cnt++;
	}
	int n, ans;
	int link[MAXN];
	bool use[MAXN];
	Hungary ( ) { };
	Hungary ( int _n ) : n(_n) { };
	void ini ( int n ) {
		this->n = n;
		cnt = 0; memset( head, -1, sizeof(head) );
	}
private:
	bool dfs ( int u ) {
		for ( int k = head[u]; k != -1; k = e[k].to ) {
			int v = e[k].v;
			if ( use[v] ) continue;
			use[v] = true;
			if ( link[v] == -1 || dfs ( link[v] ) ) {
				link[v] = u;
				return true;
			}
		}
		return false;
	}
public:
	int run ( ) {
		ans = 0;
		memset ( link, 255, sizeof ( link ) );
		for ( int i = 0; i < n; ++i ) {
			memset ( use, 0, sizeof ( use ) );
			if ( dfs ( i ) ) 
				++ans;
		}
		return ans;
	}
}h;


int main ( ) {
	int n,
		u, num, v; // char ch;

	while ( ~ sc ( "%d", &n ) ) {

		h.ini( n );

		for ( int i = 0; i < n; ++i ) {
			// scanf ( "%d%c%c%c%d%c)", &u, &ch, &ch, &ch, &num, &ch );
			scanf ( "%d: (%d)", &u, &num );
			for ( int j = 0; j < num; j++ ) {
				scanf ( "%d", &v );
				h.add( u, v );
			}
		}

		pf ( "%d\n", n-h.run()/2 );


	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值