Asteroids

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 29547   Accepted: 15807

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.

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 must shoot.

Sample Input

3 4
1 1
1 3
2 2
3 2

Sample Output

2

Hint

INPUT DETAILS: 
The following diagram represents the data, where "X" is an asteroid and "." 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), and then she may fire down column 2 to destroy the asteroids at (2,2) and (3,2).

Source

USACO 2005 November Gold 代码看似很长,实际上一半是注释。  
  1 /*
  2 题意:给定网格中的一些点,每次可以覆盖一行(和)一列(行列都覆盖)
  3 求最小覆盖
  4 解:看作二分图,求最大匹配数,最大匹配时,满足最小覆盖
  5 */
  6 
  7 #include <cstdio>
  8 #include <cstring>
  9 
 10 using namespace std;
 11 
 12 const int max_N = 500+5;
 13 const int max_K = 1e4+10;
 14 // e存储边信息
 15 // pred?存储临接信息
 16 int n,k,e[max_N][max_N],pred[max_N],queue[250010];
 17 // cx,cy,分别表示x集合的匹配和y集合的匹配信息
 18 int cx[max_N],cy[max_N];
 19 
 20 // 求最大匹配数,x集合与y集合在满足题目条件下的的最大匹配数
 21 // 即为最小覆盖数
 22 int maxmatch()
 23 {
 24     // y记录之后广搜中,从队列中取出的数
 25     // 由于x已经匹配,用y记录这一x可以匹配的y
 26     int y;
 27     int cur,tail,res=0;
 28     // 初始化为-1
 29     memset(cx,0xff,sizeof(cx));
 30     memset(cy,0xff,sizeof(cy));
 31     //printf("%d\n",cx[1]);
 32 
 33     for(int i=1;i<=n;++i)
 34     {
 35         // 找到x集合中每个未覆盖点i进行一次交错轨
 36         if(cx[i]!=-1)
 37         {
 38             continue;
 39         }
 40 
 41         //初始化pred数组为-2
 42         for(int j=1;j<=n;++j)
 43         {
 44             pred[j]=-2;
 45         }
 46         // 队列初始化
 47         cur=0;
 48         tail=0;
 49         // x已经匹配,将所有与x临接的顶点加入队列进行寻找
 50         for(int j=1;j<=n;++j)
 51         {
 52             if(e[i][j])
 53             {
 54                 // 用pred【j】==-1,表示已遍历到的临接顶点
 55                 pred[j]=-1;
 56                 queue[tail]=j;
 57                 ++tail;
 58             }
 59         }
 60 
 61         // BFS
 62         while(cur<tail)
 63         {
 64             // 从队列中取出一个数
 65             y=queue[cur];
 66             // 找到了一个未匹配的点,则找到了一条交错轨
 67             if(cy[y]==-1)
 68             {
 69                 break;
 70             }
 71             // 没找到交错轨,继续寻找队列中下一节点
 72             ++cur;
 73             // 由于当前点已经匹配给了cy[y]
 74             // 从cy[y]出发,将其邻接点加入队列
 75             for(int j=1;j<=n;++j)
 76             {
 77                 if(pred[j]==-2 && e[ cy[y] ][j])
 78                 {
 79                     // 将与y匹配的x所在行中的所有点加入队列
 80                     // 并用pred记录x所对应的y值
 81                     pred[j]=y;
 82                     queue[tail]=j;
 83                     ++tail;
 84                 }
 85             }
 86         }
 87         // 如果没有找到交错轨,则不能得到更大的匹配数
 88         // 跳过进行下次寻找
 89         if(cur==tail)
 90         {
 91             continue;
 92         }
 93         
 94         // 当找到了交错轨时,即找到了一个未匹配的点(cy[y]==-1)时
 95         // 更改交错轨上的匹配状态
 96         while(pred[y]>-1)
 97         {
 98             // 之前y匹配的那个x匹配的数改成当前y
 99             cx[ cy[ pred[y] ] ] = y;
100             // 现在的y匹配前一个y匹配的那个x,空出现在的y待匹配
101             cy[y] = cy[ pred[y] ];
102             // y 更新为可行交错轨上前一个y
103             y=pred[y];
104         }
105         
106         // cx[i]是空闲未匹配的,最早的cy[y]已被空出
107         cy[y]=i;
108         cx[i]=y;
109         // 匹配成功,匹配数+1
110         ++res;
111     }
112 
113     // 二分图的最小顶点覆盖数=最大匹配数
114     // 返回最小顶点覆盖数,即为所求结果
115     return res;
116 }
117 
118 int main()
119 {
120     int x,y;
121     while(scanf("%d %d",&n,&k)!=EOF)
122     {
123         memset(e,0,sizeof(e));
124         for(int i=1;i<=k;++i)
125         {
126             scanf("%d %d",&x,&y);
127             e[x][y]=1;
128         }
129         printf("%d\n",maxmatch());
130     }
131     return 0;
132 }

 

上一篇:POJ2728——最优比例生成树


下一篇:(九)OpenCV其它功能_02_离散傅立叶变换