hdu1281棋盘游戏(二分图匹配+枚举)

PS:题目是中文的就不再翻译了。

思路:

求最大可以放的‘车’数目:将行与列分成两个集合,每行/列都作为1个集合中的点,题目所给的行与列的交点当作边。直接二分图匹配即可。

求‘重要’的顶点个数:枚举每个顶点(二分图中的边);将他们去掉后,再重新进行一次匹配。如果匹配数减少,则说明该顶点是一个‘重要’的点。

#include 
#include 
#include 
#include 
#include 
using namespace std;
#define N 350
#define INF 0x3f3f3f3f
struct node
{
	int v, next;
}a[N*N];
int head[N], used[N], girl[N];
int n, m, k, cnt, t = 0;
void add(int u, int v)
{
	a[cnt].v = v;
	a[cnt].next = head[u];
	head[u] = cnt++;
}
int find(int x, int d)
{
	int i;
	
	for(i = head[x]; i != -1; i = a[i].next)
	{		
		if(d == -1 || i != d)
		{
			int v = a[i].v;
			
			if(used[v] == -1)
			{
				used[v] = 1;
				if(girl[v] == -1 || find(girl[v], d))
				{
					girl[v] = x;
					return 1;
				}
			}
		}
	}
	return 0;
}
int main()
{
	while(scanf("%d%d%d", &n, &m, &k) != EOF)
	{
		int i, j;
		int u, v, con = 0;
		
		cnt = 0;
		memset(head, -1, sizeof(head));
		for(i = 1; i <= k; i++)
		{
			scanf("%d%d", &u, &v);
			add(u, v);
		}
		int ans = 0;
		
		memset(girl, -1, sizeof(girl));
		for(i = 1; i <= n; i++)
		{
			memset(used, -1, sizeof(used));
			if(find(i, -1))
				ans++;
		}
		for(i = 0; i < cnt; i++)
		{
			int res = 0;
			
			memset(girl, -1, sizeof(girl));
			for(j = 1; j <= n; j++)
			{
				memset(used, -1, sizeof(used));
				if(find(j, i))
					res++;
			}
			if(res != ans)
				con++;
		}
		printf("Board %d have %d important blanks for %d chessmen.\n", ++t, con, ans);
	}
	return 0;
}


你可能感兴趣的:(acm)