POJ 3041 Asteroids 二分图

原题连接:http://poj.org/problem?id=3041

Asteroids

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 17985   Accepted: 9798

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

题意:

给你一个$N*N$的棋盘,其中某些地方有棋子,你可以每次消除一列或者一行,问你至少需要多少次操作,把棋子消除完。

题解:

这是一道二分匹配的经典问题。将每个棋子的横纵坐标连边,那么就会构成一个二分图,问题就转化为求解这个二分图的最小点覆盖。由最小点覆盖就是最大匹配,跑一发dinic就好。

代码:

#include<iostream>
#include<stack>
#include<vector>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<queue>
#define MAX_S (1<<10)+10
#define MAX_V 1234
#define MAX_N MAX_V
#define INF 1000009
using namespace std;

struct edge {
    int to, cap, rev;
    bool isRev;

    edge(int t, int c, int r, bool i)
            : to(t), cap(c), rev(r), isRev(i) { }

    edge() { }
};

template <class T>
inline bool scan_d(T &ret)
{
    char c;
    int sgn;
    if(c=getchar(),c==EOF) return 0; //EOF
    while(c!=‘ -‘ &&(c<‘0‘ ||c>‘9‘ )) c=getchar();
    sgn=(c==‘ -‘ )?-1:1;
    ret=(c==‘ -‘ )?0:(c-‘0‘ );
    while(c=getchar(),c>=‘0‘ &&c<=‘9‘ ) ret=ret*10+(c-‘0‘ );
    ret*=sgn;
    return 1;
}

vector<edge> G[MAX_N];
int level[MAX_V];
int iter[MAX_V];

void init(int totNode) {
    for (int i = 0; i <= totNode; i++)
        G[i].clear();
    memset(level, 0, sizeof(level));
    memset(iter, 0, sizeof(iter));
}

void add_edge(int from,int to,int cap) {
    G[from].push_back(edge (to, cap, G[to].size(),0));
    G[to].push_back(edge (from, 0, G[from].size() - 1,1));
}

void bfs(int s) {
    queue<int> que;
    memset(level, -1, sizeof(level));
    level[s] = 0;
    que.push(s);
    while (!que.empty()) {
        int v = que.front();
        que.pop();
        for (int i = 0; i < G[v].size(); i++) {
            edge &e = G[v][i];
            if (e.cap > 0 && level[e.to] < 0) {
                level[e.to] = level[v] + 1;
                que.push(e.to);
            }
        }
    }
}

int dfs(int v,int t,int f) {
    if (v == t)return f;
    for (int &i = iter[v]; i < G[v].size(); i++) {
        edge &e = G[v][i];
        if (e.cap > 0 && level[v] < level[e.to]) {
            int d = dfs(e.to, t, min(f, e.cap));
            if (d > 0) {
                e.cap -= d;
                G[e.to][e.rev].cap += d;
                return d;
            }
        }
    }
    return 0;
}

int max_flow(int s,int t) {
    int flow = 0;
    for (; ;) {
        bfs(s);
        if (level[t] < 0)return flow;
        memset(iter, 0, sizeof(iter));
        int f;
        while ((f = dfs(s, t, INF)) > 0) {
            flow += f;
        }
    }
}

int n,m;
int S=1233,T=1212;

int main() {
    cin.sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int u, v;
        cin >> u >> v;
        add_edge(u, v+n, 1);
    }
    for (int i = 1; i <= n; i++) {
        add_edge(S, i, 1);
        add_edge(i+n, T, 1);
    }
    cout << max_flow(S, T) << endl;
    return 0;
}
时间: 2024-10-09 14:46:10

POJ 3041 Asteroids 二分图的相关文章

POJ 3041 Asteroids (二分图最小点覆盖)

题目链接:http://poj.org/problem?id=3041 在一个n*n的地图中,有m和障碍物,你每一次可以消除一行或者一列的障碍物,问你最少消除几次可以将障碍物全部清除. 用二分图将行(左边)和列(右边)用障碍物联系起来,比如(2,3)有个障碍物,那么左边的2和右边的3连边.边的个数就是障碍物的个数,点的个数就是次数,所以问题就变成了用少的点覆盖全部的边,也就是最小点覆盖问题.二分图中,最小点覆盖=最大匹配数. 1 //最小点覆盖 = 最大匹配 2 #include <iostre

poj - 3041 Asteroids (二分图最大匹配+匈牙利算法)

http://poj.org/problem?id=3041 在n*n的网格中有K颗小行星,小行星i的位置是(Ri,Ci),现在有一个强有力的武器能够用一发光速将一整行或一整列的小行星轰为灰烬,想要利用这个武器摧毁所有的小行星最少需要几发光束. 主要是构图,将每一行当成一个点,构成集合1,每一列也当成一个点,构成集合2,每一个障碍物的位置坐标将集合1和集合2的点连接起来,也就是将每一个障碍物作为连接节点的边,这样可以得出本题是一个最小点覆盖的问题==二分图的最大匹配. 就可以通过匈牙利算法求解.

POJ 3041 Asteroids(二分图模板题)

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. Fortun

【网络流#6】POJ 3041 Asteroids 二分图最大匹配 - 《挑战程序设计竞赛》例题

学习网络流中ing...作为初学者练习是不可少的~~~构图方法因为书上很详细了,所以就简单说一说 把光束作为图的顶点,小行星当做连接顶点的边,建图,由于 最小顶点覆盖 等于 二分图最大匹配 ,因此求二分图最大匹配即可. 邻接矩阵,DFS寻找增广路,匈牙利算法 邻接矩阵:复杂度O(n^3) 如果使用邻接表:复杂度O(n*m) #include<cstdio> #include<cstring> #include<cmath> #include<iostream>

POJ 3041 Asteroids 二分图之最大匹配

题意:在一个网格中有若干个点,每一次可以清除一行或者一列,问最少几次可以将网格中的点全部清除. 思路:这个题是一个入门的最大匹配题(这个好像不是思路..).一般的方式就是将 行 看作集合A,列 看作集合B. 这么说有点抽象.举个例子:2行3列的矩阵可以看作是集合A={1,2}与B={1,2,3},假设矩阵[1][2] 存在点(别忘了题意),则A中的元素1与B中元素2连有一条边. 这样就可以将题给矩阵转化为二分图,再利用匈牙利算法得到最大匹配数就是答案了. 1 #include<iostream>

POJ - 3041 Asteroids 二分图 最小点覆盖

题目大意:在一个N * N的网格中,有M个障碍物,现在你有一把武器,这个武器可以消除任意一行或者一列的障碍物,现在要求将所有障碍物消完,问至少使用这把武器多少次 解题思路:想了老半天怎么解决行和列的问题...怎么表示两个点集 最后突然想到,既然不知道怎么处理行列,就将行列分别分成两个点集吧,点就代表行和列之间的关系,就这样交了一发,A了. 其实,这确实是,行列之间的连线(点)只要能用某些点表示就可以了.那些点就是所有连线的其中一个端点,这样这些点就能画出所有的连线了,所有的连线都能被表示到了,就

二分图匹配(匈牙利算法) POJ 3041 Asteroids

题目传送门 1 /* 2 题意:每次能消灭一行或一列的障碍物,要求最少的次数. 3 匈牙利算法:把行和列看做两个集合,当有障碍物连接时连一条边,问题转换为最小点覆盖数==二分图最大匹配数 4 趣味入门:http://blog.csdn.net/dark_scope/article/details/8880547 5 */ 6 #include <cstdio> 7 #include <algorithm> 8 #include <cstring> 9 #include

POJ 3041 Asteroids (匈牙利算法)

Asteroids Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14388 Accepted: 7828 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 astero

poj 3041——Asteroids

poj       3041——Asteroids Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22604   Accepted: 12247 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 g