我仿佛又开始写水题了…好颓废…花了五分钟A了…
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.
贝茜想驾驶她的飞船穿过危险的小行星群.小行星群是一个NxN的网格(1≤N≤500),在网格内有K个小行星(1≤K≤10000). 幸运地是贝茜有一个很强大的武器,一次可以消除所有在一行或一列中的小行星,这种武器很贵,所以她希望尽量地少用.给出所有的小行星的位置,算出贝茜最少需要多少次射击就能消除所有的小行星.
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.
第1行:两个整数N和K,用一个空格隔开.
第2行至K+1行:每一行有两个空格隔开的整数R,C(1≤R,C≤N),分别表示小行星所在的行和列.
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
INPUT DETAILS:
The following diagram represents the data, where “X” is an
asteroid and “.” is empty space:
X.X
.X.
.X.
Sample Output
2
OUTPUT DETAILS:
Bessie may fire across row 1 to destroy the asteroids at (1,1) and
(1,3), and then she may fire down column 2 to destroy the asteroids
at (2,2) and (3,2).
显然这道题直接行向边连边跑二分图或者最大流就可以了,正确性是显然的
考虑这样一张图
我们如果对其行连列构建二分图,其中列的坐标是他的坐标加n,会得到这样的二分图
观察这张二分图,我们会发现对于行来说,我们的2行3行5行都可以连8,然而8代表的是(8-5)=第3列,那么意思就是说,无论连(2,8),(3,8)或者是(5,8),都只能连一条边,也就是说如果选择第三列,cnt++,而如上所述3个点都会被覆盖。
这样思考,如果二分图里存在一个匹配组合没有被匹配(也就是找到一个点,他的行和列都没有被打的话),一定要匹配他才能消灭它,如果对于(2,8),(3,8)或者是(5,8)的清况,匹配了一次之后剩下的两个都匹配不上了,就说明已经被打了,不能再匹配了(也即这三个点的行或者列已经被打了)
最多的情况下,我们需要覆盖所有列出现的情况,所以我们只需要寻找最大匹配就行了
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#define MAXN 10000+50
using namespace std;
int n,m;
bool vis[MAXN];
struct Line{
int from,to,nxt;
}line[MAXN];
int head[MAXN],tail;
int girl[MAXN];
void add_line(int from,int to){
tail++;
line[tail].from=from;
line[tail].to=to;
line[tail].nxt=head[from];
head[from]=tail;
}
bool find(int u){
for(register int i=head[u];i;i=line[i].nxt){
int v=line[i].to;
if(!vis[v]){
vis[v]=true;
if(girl[v]==-1||find(girl[v])){
girl[v]=u;
return true;
}
}
}
return false;
}
int main(){
scanf("%d%d",&n,&m);
for(register int i=1;i<=m;i++){
int from,to;
scanf("%d%d",&from,&to);
add_line(from,n+to);
}
memset(girl,-1,sizeof(girl));
int cnt=0;
for(register int i=1;i<=m;i++){
memset(vis,false,sizeof(vis));
if(find(i))cnt++;
}
printf("%d\n",cnt);
return 0;
}