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

题目连接

题目大意:一个n*n的太空矩阵,其中有m个地方存在小行星,有一种武器,该武器可以发射光束,这种光束可以一次性消灭一行或者一列小行星。问:消灭所有的小行星,最少需要多少发光束。

题解:这个题目咋一看看不出来是二分图的题目。设有小行星位于(x,y)。那么可以对x行发射光束,也可以对y列发射光束。那么分别以x和y为定点连一条边。这条边就表示这里有一颗行星。这样图就构造完了。

注意图中的边表示的是行星,定点表示的是某行或者某列。我们要消灭所有的行星,也就是需要“消灭”所有的边。所以我们只需要找到该图的最小顶点覆盖就可行了,由于二分图中,最小定点覆盖等于最大匹配,因此只需要找改图的最大匹配。可以采用dicnic最大流算法,也可以用匈牙利算法。

code:

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int N=500+7;
int n,m;
int mark[N];
int p[N];
vector<int >ve[N];
bool find(int x){
    for(int i=0;i<ve[x].size();i++){
        if(mark[ve[x][i]]==0){
            mark[ve[x][i]]=1;
            if(p[ve[x][i]]==0||find(p[ve[x][i]])){
                p[ve[x][i]]=x;
                return 1;
            }
        }
    }
    return 0;

}

void KM(){
    int ans=0;
    for(int i=1;i<=n;i++){
        memset(mark,0,sizeof mark);
        if(find(i)) ans++;
    }
    cout<<ans<<endl;
}
int main(){
    cin>>n>>m;
    int x,y;
    for(int i=1;i<=m;i++){
        cin>>x>>y;
        ve[x].push_back(y);
    }
    KM();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Accepting/p/13366795.html