EOJ 2069 Asteroids 二分图最大匹配

Description
Bessie wants to navigate her spaceship through a dangerous asteroid field inthe 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 pointsof the grid.
Fortunately, Bessie has a powerful weapon that can vaporize all the asteroidsin any given row or column of the grid with a single shot.This weapon is quiteexpensive, so she wishes to use it sparingly.Given the location of all theasteroids in the field, find the minimum number of shots Bessie needs to fireto 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 mustshoot.

Sample Input
3 4
1 1
1 3
2 2
3 2

Sample Output
2
INPUT DETAILS:
The following diagram represents the data, where "X" is an asteroidand "." is empty space:
X.X
.X.
.X.

OUTPUT DETAILS:
Bessie may fire across row 1 to destroy the asteroids at (1,1) and (1,3), andthen she may fire down column 2 to destroy the asteroids at (2,2) and (3,2).

 

 

 

 

题目分析:将目标点的横坐标和纵坐标作为两个集合,则一个目标就是一条边,一枪可以消灭与这个点邻接的所有边,故求一个图的最小点覆盖即可,亦即二分图最大匹配数。

用匈牙利算法找增广路径。用dfs实现,初始化所有点为未盖点。依次搜索每一个点,如果存在增广路,则匹配数加1;

 

 

 

 

 

AC代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <string>

#include <vector>

#include <map>

#include <algorithm>

 

using namespace std;

const int MAXN=505;

vector<int> g[MAXN]; //邻接表储存图

int n,m;

bool vis[505];//标记点

int link[MAXN];//匹配关系,初始化为-1

bool dfs(int s){

   for(int i=0;i<g[s].size();++i){

       int u=g[s][i];

       if(vis[u]) continue;

       vis[u]=true;

       if(link[u]==-1 || dfs(link[u])){//u未覆盖,或u的匹配邻接未盖点

           link[u]=s;

           return true;

       }

    }

   return false;

}

 

int hungry(){

   int ans=0;

   memset(link,-1,sizeof(link));//初始化每个点未覆盖

   for(int i=1;i<=n;++i){

       memset(vis,false,sizeof(vis));

       if(dfs(i))  ans++;//存在增广路径,且每次增广路径长度比匹配数大一

    }

   return ans;

}

 

int main()

{

   scanf("%d%d",&n,&m);

   for(int i=1;i<=n;++i)

       g[i].clear();

   for(int i=0;i<m;++i){

       int x,y;

       scanf("%d%d",&x,&y);

       g[x].push_back(y);

    }

   printf("%d\n",hungry());

   return 0;

}

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值