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;

}

 

 

 

 

 

 

### EOJ2654 题目解析与解法建议 EOJ2654 是华东师范大学在线评测系统(EOJ)中的一道编程题目。根据EOJ系统的常见题型和风格,这类题目通常涉及基础的数据结构操作、算法实现或数学建模。虽然没有直接提及EOJ2654的具体题目内容,但可以从EOJ系统的典型题目特征出发,结合常见的编程题类型,给出可能的解题思路与实现方法。 #### 题目类型推测 EOJ系统中常见的题目包括但不限于: - 数值计算与数学建模 - 字符串处理与模式匹配 - 数据结构操作(如栈、队列、链表等) - 图论与搜索算法 - 动态规划与贪心策略 根据题目编号(2654)以及EOJ的出题规律,该题可能属于**中等难度**,可能涉及**数学建模**或**字符串处理**。 #### 示例解法思路(假设题目为字符串处理) 假设题目要求判断某个字符串是否为回文串(Palindrome),可以采用如下C++实现: ```cpp #include <iostream> #include <string> #include <algorithm> using namespace std; int main() { string s; cin >> s; string rev = s; reverse(rev.begin(), rev.end()); if (s == rev) { cout << "Yes" << endl; } else { cout << "No" << endl; } return 0; } ``` #### 示例解法思路(假设题目为数学建模) 若题目要求求解某个数列的第n项,例如斐波那契数列,可以使用递归或迭代方法。以下是迭代方法的实现: ```cpp #include <iostream> using namespace std; long long fib(int n) { long long a = 0, b = 1, c; if (n == 0) return a; for (int i = 2; i <= n; i++) { c = a + b; a = b; b = c; } return b; } int main() { int n; cin >> n; cout << fib(n) << endl; return 0; } ``` #### 注意事项 在EOJ系统中,需要注意以下几以避免运行时错误或超时: 1. **输入输出效率**:对于大规模输入数据,建议使用`scanf`和`printf`代替`cin`和`cout`以提高效率[^1]。 2. **数据类型选择**:在涉及大数运算时,应使用`long long`等大整数类型以防止溢出[^4]。 3. **边界条件处理**:特别注意输入数据的边界情况,如最小值、最大值等。 4. **代码简洁性与可读性**:保持代码结构清晰,避免不必要的复杂逻辑,以便调试与优化。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值