POJ 3041 Asteroids(最小顶点覆盖,匈牙利算法模板)

来源:互联网 发布:java多线程经典书籍 编辑:程序博客网 时间:2024/05/16 11:20

题目地址
题意:你有一个n*n的棋盘,棋盘上有m个棋子,你有一种技能可以把一行或者一列的棋子全部清掉,问你要把棋盘上所有的棋子清掉最少要使用多少次技能
思路:你按照当(x,y)上有点的时候建一条连接x与y+n的边,这样的话因为是把一行或者一列删除掉,所以就是求最少有多少个点可以连通整个图,这样就转变为最小顶点覆盖的题目了,根据下面的转换就直接用匈牙利算法的模板就好了。

最小顶点覆盖数=最大匹配数
最小路径覆盖=|N|-最大匹配数
二分图最大独立集=顶点数-二分图最大匹配

邻接表存储

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#define N 1010#define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1e9 + 7;int n, m;struct Hungarian {    vector<int> mapp[N];    bool vis[N];//是否为匹配点    int mark[N];//该边与哪个点构成的边为匹配边    void init() {        for (int i = 0; i <= n; i++) {            mapp[i].clear();        }        memset(mark, -1, sizeof(mark));    }    void add(int a, int b) {        mapp[a].push_back(b);        mapp[b].push_back(a);    }    bool dfs(int u) {        for (int i = 0; i < mapp[u].size(); i++) {            int v = mapp[u][i];            if (!vis[v]) {                vis[v] = true;                if (mark[v] == -1 || dfs(mark[v])) {                    mark[u] = v;                    mark[v] = u;                    return true;                }            }        }        return false;    }    int solve() {        int sum = 0;        for (int i = 1; i <= n; i++) {//枚举非匹配点            if (mark[i] == -1) {                memset(vis, false, sizeof(vis));                if (dfs(i)) {                    sum++;//最大匹配的个数                }            }        }        return sum;    }}hungarian;int main() {    int a, b;    cin.sync_with_stdio(false);    while (cin >> n >> m) {        hungarian.init();        for (int i = 0; i < m; i++) {            cin >> a >> b;            hungarian.add(a, n + b);        }        cout << hungarian.solve() << endl;    }    return 0;}
原创粉丝点击