二分图_最大独立点集

二分图_最大独立点集

最大独立集是一个点集, 使得其中任意两点之间在图中没有对应边。
对于一般得图来说 ,最大独立集是一个NP完全问题,对于二分图来说最大独立集 = |V| - 二分图得最大匹配数。

这个结论很显然。

题目:POJ3041
Description

Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 <= N <= 500). The grid contains K asteroids (1 <= K <= 10,000), which are conveniently located at the lattice points of the grid.

Fortunately, Bessie has a powerful weapon that can vaporize all the asteroids in any given row or column of the grid with a single shot.This weapon is quite expensive, so she wishes to use it sparingly.Given the location of all the asteroids in the field, find the minimum number of shots Bessie needs to fire to eliminate all of the asteroids.
Input

  • Line 1: Two integers N and K, separated by a single space.

  • Lines 2…K+1: Each line contains two space-separated integers R and C (1 <= R, C <= N) denoting the row and column coordinates of an asteroid, respectively.
    Output

  • Line 1: The integer representing the minimum number of times Bessie must shoot.
    Sample Input

3 4
1 1
1 3
2 2
3 2
Sample Output

2

题目大意:
老师要带学生门出去远行,其中男生和女生之间可能会谈恋爱,单这个老师想要在学生们谈恋爱的可能性尽可能小的情况喜爱,带出去最多的学生。

思路:
可以让男生和女生构建一张二分图,其中可能会谈恋爱的学生们之间就连一条边,有边的人不能同时取,又需要带最多的人出去,就是让我们求这个二分图的最大独立集
= |V| - 最大匹配数

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;

const int maxn = 550;

struct Person {
	int height;
	char sex[3];
	char music[105];
	char sport[105];
}m[maxn], f[maxn];

int t, n, n_m, n_f;
int h[maxn], e[maxn * maxn], ne[maxn * maxn], idx;
bool vis[maxn];
int match[maxn];

inline void add(int a, int b) {
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

inline bool judge_mu(char s1[], char s2[]) {
	int a, b;
	a = strlen(s1), b = strlen(s2);
	if(a != b) return false;
	else {
		for(int i = 0; i < a; i ++) 
			if(s1[i] != s2[i])
				return false;
				
		return true;
	}
}

inline bool judge_sp(char s1[], char s2[]) {
	int a, b;
	a = strlen(s1), b = strlen(s2);
	if(a != b) return true;
	else {
		for(int i = 0; i < a; i ++)
			if(s1[i] != s2[i])
				return true;
				
		return false;
	}
}

inline bool find(int u) {
	for(int i = h[u]; i != -1; i = ne[i]) {
		int v = e[i];
		if(!vis[v]) {
			vis[v] = true;
			if(!match[v] || find(match[v])) {
				match[v] = u;
				return true;
			}
		}
	}
	
	return false;
}

int main(void) {
//	freopen("in.txt", "r", stdin);
	scanf("%d", &t);
	while(t --) {
		//处理输入 
		scanf("%d", &n);
		memset(h, -1, sizeof h);
		for(int i = 1; i <= n; i ++) {
			int height;
			char sex[3], music[105], sport[105];
			scanf("%d%s%s%s", &height, sex, music, sport);
			if(sex[0] == 'M') {
				m[++ n_m].height = height;
				strcpy(m[n_m].sex, sex);
				strcpy(m[n_m].music, music);
				strcpy(m[n_m].sport, sport);
			} else {
				f[++ n_f].height = height;
				strcpy(f[n_f].sex, sex);
				strcpy(f[n_f].music, music);
				strcpy(f[n_f].sport, sport);
			}
		}
		
		//加边 
		for(int i = 1; i <= n_m; i ++) {
			for(int j = 1; j <= n_f; j ++) {
				if(abs(m[i].height - f[j].height) <= 40 && judge_mu(m[i].music, f[j].music) && judge_sp(m[i].sport, f[j].sport)) {
					add(i, j + n_m);
				}
			}
		}
		
		//计算最终答案 
		int ans = 0;
		for(int i = 1; i <= n_m; i ++) {
			memset(vis, false, sizeof vis);
			if(find(i)) ans ++;
		}
		
		printf("%d\n", n - ans);
		
		//初始化
		memset(match, 0, sizeof match); 
		n_m = n_f = 0;
		idx = 0;
	}
	
//	fclose(stdin);
	return 0;	
} 

写代码的时候被坑的点:
1.字符串的复制,可以直接用strcpy。 !!
2.每次初始化的时候,记得需要初始化idx, 即idx = 0; !!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值