POJ 3041 Asteroids 二分图的最大匹配(最小点颠覆集)

来源:互联网 发布:手机淘宝新手怎么拿货 编辑:程序博客网 时间:2024/05/17 04:35

POJ 3041 Asteroids  二分图的最大匹配(最小点颠覆集)

题意:一直可以发射炮弹,每个炮弹可以打掉 每一行或每一列的所有行星 求如何发射才可以使炮弹使用的数量最少


有题意可以抽象出 两类出来  每一行的坐标可以看成 一个集合 x

每一列的坐标可以看成 一个集合 y

行星 则可以看成是连接行与列的线

例如

X*X             //可以看成是行坐标元素 1 通过(1,1)(1,3)分别与列 坐标元素 1, 3 相连接


这就是二分图的最小点覆盖集问题




#include<iostream>#include<cstring>#include<cstdio>using namespace std;int n,k;  //n矩阵规格,k星体数量int V1,V2;       //二分图顶点集/*矩阵的行列分别属于二分图的两个顶点集V1、V2,其中行x∈V1,列y∈V2*/bool grid[501][501];  //存储数据方式:可达矩阵bool vis[501];     //记录V2的点每个点是否已被搜索过int link[501];     //记录 V2中的点y 在 V1中 所匹配的点x的编号int m;  //最大匹配数/*Hungary Algorithm*/bool dfs(int x){    for(int y=1; y<=V2; y++)        if(grid[x][y] && !vis[y])  //x到y相邻(有边) 且 节点y未被搜索        {            vis[y]=true;   //标记节点y已被搜索            if(link[y]==0 || dfs(link[y])) //link[y]==0 : 如果y不属于前一个匹配M            {                //find(link[y] : 如果被y匹配到的节点可以寻找到增广路                link[y]=x; //那么可以更新匹配M'(用M替代M')                return true;  //返回匹配成功的标志            }        }    return false;  //继续查找V1下一个x的邻接节点}void MaxMatch(void){    for(int x=1; x<=V1; x++)    {        memset(vis,false,sizeof(vis)); //清空上次搜索时的标记        if(dfs(x))  //从V1中的节点x开始寻找增广路            m++;    }    return;}int main(void){    cin>>n>>k;    V1=V2=n;    int x,y;         //坐标(临时变量)    for(int i=1; i<=k; i++)    {        cin>>x>>y;        grid[x][y]=true;   //相邻节点标记    }    /*增广轨搜索*/    MaxMatch();    /*Output*/    cout<<m<<endl;    return 0;}


1 0
原创粉丝点击