【最大匹配】小行星

小行星

題目

貝西想以N x N網格(1 <= N <= 500)的形狀在危險的小行星場中導航她的飛船。網格包含K個小行星(1 <= K <= 10,000),它們方便地位於網格的晶格點處。

幸運的是,貝茜擁有強大的武器,可以一擊就蒸發掉網格中任何給定行或列中的所有小行星,這種武器非常昂貴,因此她希望謹慎使用。字段中,找到貝西需要射擊以消除所有小行星的最小射擊次數。

輸入

第1行:兩個整數N和K,以單個空格分隔。
第2…K + 1行:每行包含兩個空格分隔的整數R和C(1 <= R,C <= N),分別表示小行星的行和列座標。

輸出

第1行:整數,表示Bessie必須拍攝的最小次數。

輸入樣例

3 4
1 1
1 3
2 2
3 2

輸出樣例

2

輸入詳細信息

下圖表示數據,其中“ X”是小行星,“。”。是空白空間:

X  。 X 
。 X  。 
。 X  。 

輸出詳細信息

Bessie可以越過第1行射擊以摧毀1,1(1,1)1,3(1,3)處的小行星,然後她可以擊落第2列以摧毀2,2(2,2)3,2(3,2)處的小行星。

解題思路

其實這道題就是最大匹配的模板,把每個行星的的XXYY分別列成一行,建二分圖,然後把行星的XXYY的座標連起來,在查找最大匹配即可.

程序如下

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int n,k,kk,x,y,head[100001],s[100001],l[100001],ans;
struct node
{
	int to,next;
}f[1000001];
int find(int t)
{
	for (int i = head[t]; i; i = f[i].next)
	{
		int j = f[i].to;
		if (!s[j])
		{
		    int q = l[j];
		    l[j] = t;
		    s[j] = 1;
		    if (!q || find(q)) return 1;
		    l[j] = q;
		}
		
	}
	return 0;
}
int main()
{
	scanf("%d%d",&n,&k);
	for(int i = 1;i <= k; ++i)
	{
		scanf("%d%d",&x,&y);
		f[++kk].next = head[x];
		f[kk].to = y;
		head[x] = kk;
	}
	for(int i = 1;i <= n; ++i)
	{
		memset(s,0,sizeof(s));
		ans += find(i);
	}
	printf("%d",ans);
	return 0;   
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章