zoukankan      html  css  js  c++  java
  • poj3041——最小点覆盖

    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).
     
     
     
    大意:K个目标在N*N的方阵中,一次攻击可以消除同一行或同一列的目标,问最少几次攻击消除所有目标。
    题解:这题是看题解写的,建一个二分图,图一侧的定点代表行,另一侧的定点代表列,如果(x,y)有目标,就连边x->y。
    那么这题就转换为最少选多少个点,使所有边的两个定点至少有一个被选中,这就是经典模型最小点覆盖。
    结论:最小点覆盖=最大匹配。
    写的很好
     
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<ctime>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<string>
    using namespace std;
    int read(){
        int xx=0,ff=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')ff=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){xx=(xx<<3)+(xx<<1)+ch-'0';ch=getchar();}
        return xx*ff;
    }
    const int maxn=1010;
    int N,K,lin[maxn],len;
    struct edge{
    	int y,next;
    }e[10010];
    inline void insert(int xx,int yy){
    	e[++len].next=lin[xx];
    	lin[xx]=len;
    	e[len].y=yy;
    }
    int tim,pretim,match[maxn],vis[maxn],ans;
    bool hun(int x){
    	for(int i=lin[x];i;i=e[i].next)
    		if(vis[e[i].y]<=pretim){
    			vis[e[i].y]=++tim;
    			if(match[e[i].y]==0||hun(match[e[i].y])){
    				match[x]=e[i].y;
    				match[e[i].y]=x;
    				return 1;
    			}
    		}
    	return 0;
    }
    int main(){
    	//freopen("in","r",stdin);
    	//freopen("out","w",stdout);
    	N=read(),K=read();
    	for(int i=1;i<=K;i++){
    		int t1=read(),t2=read()+N;
    		insert(t1,t2);
    	}
    	for(int i=1;i<=N*2;i++)
    		if(!match[i]){
    			pretim=tim;
    			tim++;
    			if(hun(i))
    				ans++;
    		}
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    c# in deep 之LINQ简介(1)
    今天开通博客
    bzoj 4009 接水果 整体二分
    区间求mex的几种方法
    充分性,必要性,充分条件,必要条件的区别
    表达式求值(noip2015等价表达式)
    selenium-模拟鼠标
    selenium学习-ActionChains方法列表
    高手指导中手的书籍
    新生
  • 原文地址:https://www.cnblogs.com/lzhAFO/p/8064950.html
Copyright © 2011-2022 走看看