POJ3020 匹配

题目大意:给定一地图,*可以和相邻的*匹配成一对儿,问最少需要对儿匹配才能使所有*都被匹配到。

很直白的最小点覆盖,即ans = 点集数-最大匹配数。

不过一开始要对图进行遍历得到点集,找到一个*就把点集数+1,并和周围的匹配即可。为了防止重复,

我只匹配了左边和上边的点。由于用邻接表保存了双向路,所以最后匹配结果会是最大匹配的二倍。

数据范围是40*10,匈牙利即可,因此不用Karp进行优化。

附AC代码:

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
#define oo 0x3f3f3f3f
char maps[50][20];
int nums[50][20];
struct ad
{
    int next, to;
} edge[1000000];
int head[1100], edge_num, used[1100], vis[1100];
void Add(int x, int y)
{
    edge[edge_num].next = head[x];
    edge[edge_num].to = y;
    head[x] = edge_num++;
}
bool Hungary(int u)
{
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        int To = edge[i].to;
        if(!vis[To])
        {
            vis[To] = 1;
            if(!used[To] || Hungary(used[To]))
            {
                used[To] = u;
                return true;
            }
        }

    }
    return false;
}
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int m, n;
        scanf("%d %d", &m, &n);
        for(int i=0; i<m; i++)
            scanf("%s", maps[i]);
        int cnt = 0;
        memset(head, -1, sizeof(head));
        edge_num = 0;
        for(int i=0; i<m; i++)
            for(int j=0; j<n; j++)
            {
                if(maps[i][j]==‘*‘)
                {
                    cnt++;
                    nums[i][j] = cnt;
                    if(i>=1 && maps[i-1][j]==‘*‘)
                    {
                        Add(nums[i-1][j], nums[i][j]);
                        Add(nums[i][j], nums[i-1][j]);
                    }
                    if(j>=1 && maps[i][j-1]==‘*‘)
                    {
                        Add(nums[i][j], nums[i][j-1]);
                        Add(nums[i][j-1], nums[i][j]);
                    }
                }
            }
        memset(used, 0, sizeof(used));
        int ans = 0;
        for(int i=1; i<=cnt; i++)
        {
            memset(vis, 0, sizeof(vis));
            if(Hungary(i))ans++;
        }
        printf("%d\n", cnt-ans/2);
    }
    return 0;
}
时间: 2024-10-14 09:54:56

POJ3020 匹配的相关文章

POJ-3020 Antenna Placement---二分图匹配&amp;最小路径覆盖&amp;建图

题目链接: https://vjudge.net/problem/POJ-3020 题目大意: 一个n*m的方阵 一个雷达可覆盖两个*,一个*可与四周的一个*被覆盖,一个*可被多个雷达覆盖问至少需要多少雷达能把所有的*覆盖 解题思路: 把每个*城市编号,然后每相邻两个城市之间连线.这里求最少多少个雷达可以覆盖完*,就是二分图匹配中的最小路径覆盖数,但是这里的图的边是双向的.举个例子 o*o **o ooo 这里可以编号成 010 230 000 那么有边<1,3><3,1><

poj3020 Antenna Placement 匈牙利算法求最小覆盖=最大匹配数(自身对应自身情况下要对半) 小圈圈圈点

/** 题目:poj3020 Antenna Placement 链接:http://poj.org/problem?id=3020 题意: 给一个由'*'或者'o'组成的n*m大小的图,你可以用一个小圈圈圈住两个相邻的'*',问要圈住所有的'*'最少需要多少个小圈圈.(小圈圈可以相交) 思路: 先尽量圈出能圈两个且不重复圈的'*'.剩下的没有圈的'*'一定需要用一个. 所以构造二分图,求最大匹配,结果:ans = 总的'*'数量-最大匹配数*2 + 最大匹配数 = 总的'*'数量-最大匹配数:

poj3020(Antenna Placement)

题目地址:Antenna Placement 题目大意: 给你一个图里面包含“o”和“*”,*表示需要天线覆盖的区域,已知天线每次最多可以覆盖相邻的两哥*.问最少需要几个*. 解题思路: 利用二分匹配,这里不是一个集合向另一个集合的定点建图,而是由一个*点的位置向四周有*的位置建图.因为一般的二分匹配是单向边,而这个图建的是双向边 所以找到的最大匹配需要除以2. 最少需要天线的个数: 最大匹配数/2+未匹配数 而未匹配数=*的总数-匹配数/2×2=*的总数-匹配数 所以答案是*的总数-最大匹配数

linux文本三剑客匹配网卡IP地址大PK(CentOS 7系统)

    运维工程师在做配置的过程中很多时候都需要去获取目标服务器网卡上的IP地址,那究竟用什么方式获取更便捷了,博主今天就带大家使用linux文本三剑客分别获取一下网卡的IP地址,最后我们再来对比一下. 实验环境: 系统:CentOS 7.2 网卡张数:双网卡 linux文本三剑客之grep 获取ifconfig输出中的IP地址 ifconfig | egrep -o "\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-1][0-9]|22[0-3])\>.(\

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则 用了几天时间看了一下开源框架Caliburn.Micro 这是他源码的地址http://caliburnmicro.codeplex.com/ 文档也写的很详细,自己在看它的文档和代码时写了一些demo和笔记,还有它实现的原理记录一下 学习Caliburn.Micro要有MEF和MVVM的基础 先说一下他的命名规则和引导类 以后我会把Caliburn.Micro的 Actions IResult,IHandle ICondu

删除除了匹配到的所有文件以及文件夹

在linux应用中经常用到 rm 有时候只想删除除了匹配到的所有文件以及文件夹. 解决方法一:自己写一个脚本. 方法二:Bash Shell有个extglob选项,开启之后Shell可以另外识别出5个模式匹配操作符,能使文件匹配更加方便. 开启方法很简单,使用shopt命令:shopt -s extglob 开启之后,以下5个模式匹配操作符将被识别: ?(pattern-list) - 所给模式匹配0次或1次: *(pattern-list) - 所给模式匹配0次以上包括0次:+(pattern

自动匹配关键字并且标红

1. 单关键字匹配 若只需匹配 搜索内容  可以写的简单一些,代码如下: if (name != null && name.contains(mKeyWord)) {                int index = name.indexOf(mKeyWord);                int len = mKeyWord.length();                Spanned temp = Html.fromHtml(name.substring(0, index)

在JaveWeb项目中配置Spring 匿名访问时,匹配规则的变相实现/*

实现/* /** * 根据当前的URL返回该url的角色集合. * 1.如果当前的URL在匿名访问的URL集合当中时,在当前的角色中添加匿名访问的角色(SysRole.ROLE_CONFIG_ANONYMOUS). * 2.如果当前系统不存在的情况,给当前用户添加一个公共访问的角色(SysRole.ROLE_CONFIG_PUBLIC). 3.url * 和角色映射,url和参数映射,给当前用户添加一个公共的角色(SysRole.ROLE_CONFIG_PUBLIC). * * @param o

[ jquery 过滤器 slice(start, [end]) ] 此方法用于在选择器的基础之上精确筛选出匹配的子集(可以使用前导限制范围)

此方法用于在选择器的基础之上精确筛选出匹配的子集(可以使用前导限制范围): 1.start:开始选取子集的位置.第一个元素是0.如果是负数,则可以从集合的尾部开始选起 2.end:结束选取自己的位置,如果不指定,则就是本身的结尾 3.参数包含开始,不包含结束 [ start , end ) 实例: <!DOCTYPE html> <html lang='zh-cn'> <head> <title>Insert you title</title>