码迷,mamicode.com
首页 > 其他好文 > 详细

POJ - 3041 Asteroids(最小点覆盖数)

时间:2015-11-19 18:52:19      阅读:219      评论:0      收藏:0      [点我收藏+]

标签:

1、有一个n*n的矩阵,在矩阵上有k个行星,用武器射击一次可以消灭一行或者一列的行星,求消灭所有的行星的最少射击次数。

2、最小点覆盖数 = 最大匹配数

主要在于转化:看图:

技术分享

3、

技术分享
/*
顶点编号从0开始的
邻接矩阵(匈牙利算法)
二分图匹配(匈牙利算法的DFS实现)(邻接矩阵形式)
初始化:g[][]两边顶点的划分情况
建立g[i][j]表示i->j的有向边就可以了,是左边向右边的匹配
g没有边相连则初始化为0
uN是匹配左边的顶点数,vN是匹配右边的顶点数
左边是X集,右边是Y集
调用:res=hungary();输出最大匹配数
优点:适用于稠密图,DFS找增广路,实现简洁易于理解
时间复杂度:O(VE)
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

const int MAXN=512;
int uN,vN;//u,v 的数目,使用前面必须赋值
int g[MAXN][MAXN];//邻接矩阵,记得初始化
int linker[MAXN];//linker[v]=u,表示v(右边Y集合中的点)连接到u(左边X集合中的点)
bool used[MAXN];
bool dfs(int u){//判断以X集合中的节点u为起点的增广路径是否存在
    for(int v=0;v<vN;v++)//枚举右边Y集合中的点
        if(g[u][v]&&!used[v]){//搜索Y集合中所有与u相连的未访问点v
            used[v]=true;//访问节点v
            if(linker[v]==-1||dfs(linker[v])){//是否存在增广路径
                //若v是未盖点(linker[v]==-1表示没有与v相连的点,即v是未盖点),找到增广路径
                //或者存在从与v相连的匹配点linker[v]出发的增广路径
                linker[v]=u;//设定(u,v)为匹配边,v连接到u
                return true;//返回找到增广路径
            }
        }
        return false;
}
int hungary(){//返回最大匹配数(即最多的匹配边的条数)
    int res=0;//最大匹配数
    memset(linker,-1,sizeof(linker));//匹配边集初始化为空
    for(int u=0;u<uN;u++){//找X集合中的点的增广路
        memset(used,false,sizeof(used));//设Y集合中的所有节点的未访问标志
        if(dfs(u))res++;//找到增广路,匹配数(即匹配边的条数)+1
    }
    return res;
}

int main(){
    int i,ans;
    int N,K;
    int R,C;
    while(~scanf("%d%d",&N,&K)){
        uN=N;//匹配左边的顶点数
        vN=N;//匹配右边的顶点数
        memset(g,0,sizeof(g));//二分图的邻接矩阵初始化
        for(i=0;i<K;++i){
            scanf("%d%d",&R,&C);
            g[--R][--C]=1;//顶点编号从0开始的
        }
        ans=hungary();
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

POJ - 3041 Asteroids(最小点覆盖数)

标签:

原文地址:http://www.cnblogs.com/bofengyu/p/4978213.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!