二分图之最小边覆盖(poj3020)

题目:poj3020

题意:给出一个图,让你用最少的1*2的纸片覆盖掉图中的所有*出现过的地方。基本裸的最小边覆盖。

分析:

最小边覆盖 = 点总数 - 最大匹配

所以就是转化为求最大匹配。

跟前面一道题目很相似,也是相同的建图方法,奇偶性建图。

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 1200;
#define Del(x,y) memset(x,y,sizeof(x))
int map[N][N],link[N],vis[N],vlink[N];
char path[50][50];
int line[50][50];
int n,m,t,tmp1,tmp2;
bool dfs(int x)
{
    for(int i=1; i<tmp2; i++)
    {
        if(map[x][i]==1 && vis[i]==0)
        {
            vis[i]=1;
            if(link[i]==-1 || dfs(link[i]))
            {
                link[i]=x;
                return true;
            }
        }
    }
    return false;
}
void solve()
{
    int ans=0;
    Del(link,-1);
    for(int i=1; i<tmp1; i++)
    {
        Del(vis,0);
        if(dfs(i))
            ans++;
    }
    //printf("%d\n",ans);
    printf("%d\n",tmp1+tmp2-ans-2);
}
int main()
{
    int T;
    scanf("%d",&T);
    //freopen("Input.txt","r",stdin);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        Del(path,0);
        for(int i=1;i<=n;i++)
        {
            getchar();
            for(int j=1;j<=m;j++)
                scanf("%c",&path[i][j]);
        }
        Del(line,-1);
        tmp1=1,tmp2=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(path[i][j]=='*')
                {
                    if((i+j)%2==0)
                        line[i][j]=tmp1++;
                    else
                        line[i][j]=tmp2++;
                }
            }
        }

        Del(map,0);
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                if(path[i][j]=='*' && (i+j)%2==1)
                {
                    if(line[i-1][j]>=1)
                        map[line[i-1][j]][line[i][j]]=1;
                    if(line[i+1][j]>=1)
                        map[line[i+1][j]][line[i][j]]=1;
                    if(line[i][j-1]>=1)
                        map[line[i][j-1]][line[i][j]]=1;
                    if(line[i][j+1]>=1)
                        map[line[i][j+1]][line[i][j]]=1;
                }
            }
        }
        solve();
    }
    return 0;
}

二分图之最小边覆盖(poj3020)

时间: 2024-11-08 14:25:24

二分图之最小边覆盖(poj3020)的相关文章

二分图中对最小顶点覆盖、最小边覆盖、最大独立集的理解[转]

原贴链接:http://blog.csdn.net/flynn_curry/article/details/52966283 仅仅用于自己理解,若有共鸣,别太吐槽就行哈~ 首先是匈牙利算法的本质:(图参考了zxy的) 这个图要详细看完,那么刚开始我想的“找小三”实际上就是递归找增广路的过程,如果找到增广路,匹配数就一定可以加一.(代码就不上了,都是一个模板) 理解到这里其实才只是个开始,我想解决的是最大匹配与最小顶点覆盖数.最小边覆盖数.最大点独立集之间的关系是怎么得来的.首先是结论: 在任意图

[POJ3020]Antenna Placement(二分图最大匹配,最小边覆盖)

题目链接:http://poj.org/problem?id=3020 题意:要求用最少的1*2的边数覆盖掉图上的所有* 在专题里看这个图很高能所以不敢做,其实是最小边覆盖的裸题,先给*标号,随后按照每个*附近是否有*来构造二分图. 最后结果 最小边覆盖 = 节点数 - 最大匹配 (虽然和最小路径覆盖结果一样,但是是完全不同的两个事情). 最大匹配是这个图上匹配的1/2,因为建图的时候是双向的. 1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗

POJ3020 Antenna Placement【二分图最小边覆盖】

题目链接: http://poj.org/problem?id=3020 题目大意: 在N*M的矩阵中,有K个城市要覆盖无线网.而一个无线网基站只能覆盖左右相邻或是上下相邻的两个 城市.问:至少放置多少个基站,能将这K个城市全部覆盖.输入数据时,'*'表示城市,'o'表示空地. 思路: K个城市作为K个点,编号为1~K.如果有两个城市相邻,则两个城市之间建立一条双向边.现在问题 变为了怎么从图中选择最少的边,使得能够覆盖所有的点.可以用二分图最小边覆盖来做.首先遍历 原图,对K个城市编号,存入i

二分图最大匹配,最小路径覆盖,最小点覆盖,最大独立集,最小边覆盖与建图方法

转载请注明出处(别管写的好坏,码字也不容易):http://blog.csdn.net/hitwhacmer1 前言:         有自己写的,有摘的别人的,前面是摘的,也是无心整理,出错是难免的,反正我都不会证明,智人见智,别被我误导了. §1图论点.边集和二分图的相关概念和性质 点覆盖.最小点覆盖 点覆盖集即一个点集,使得所有边至少有一个端点在集合里.或者说是"点" 覆盖了所有"边"..极小点覆盖(minimal vertex covering):本身为点覆

POJ2724 Purifying Machine【二分图最小边覆盖】

题目链接: http://poj.org/problem?id=2724 题目大意: 有2^N个奶酪,编号从000-00到111-11,现在有台机器有N个开关,每个开关的状态有3个, 分别是'0'.'1'.'*',每个开关只能有一个状态存在.'*'状态可以替代'0'或'1'状态.比如11*1, 对应为1111或1101.现在有M个奶酪被感染了,每个奶酪的编号为长度为N的二进制字符串. 和开关一样,每一位上除了能为'1'.'0'之外,还可以是'*',表示既能是'0',也能是'1'.比如说 1*1,

POJ3020(最小边覆盖)

Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8924   Accepted: 4428 Description The Global Aerial Research Centre has been allotted the task of building the fifth generation of mobile phone nets in Sweden. The most st

poj 3020Antenna Placement 最小边覆盖

//最小边覆盖 //最小边覆盖=最大独立集=n-最大匹配 //这个是在原图是二分图上进行的 //由于此题为无向图 //最小边覆盖=最大独立集=n-最大匹配/2; #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 45*15; int line[maxn][maxn]; int match[maxn]; int vis[maxn]; cha

二分图&amp;网络流&amp;最小割等问题的总结

二分图基础: 最大匹配:匈牙利算法 最小点覆盖=最大匹配 最小边覆盖=总节点数-最大匹配 最大独立集=点数-最大匹配 网络流: 带下界网络流 最小割问题的总结: *意义 1.加inf的边表示不能被割,通常用于体现某个点必须属于某个集合 连边(s,u,w)代表如果u不在s割的话需要付出代价w 2.连边(u,v,w)代表如果u在s割,v在t割需要付出代价w 但注意,如果u在t割,v在s割是不需要付出代价的. 那么如果连边(u,v,w)以及(v,u,w)则说明当u与v所属割不同的时候需要付出代价w *

最小路径覆盖和最小边覆盖及相关性质

[最小路径覆盖] 首先给出公式:DAG的最小路径覆盖数=DAG图中的节点数-相应二分图中的最大匹配数. 一个PXP的有向图中,路径覆盖就是在图中找一些路径,使之覆盖了图中的所有顶点,且任何一个顶点有且只有一条路径与之关联:(如果把这些路径中的每条路径从它的起始点走到它的终点,那么恰好可以经过图中的每个顶点一次且仅一次):如果不考虑图中存在回路,那么每条路径就是一个弱连通子集. 由上面可以得出: 1.一个单独的顶点是一条路径: 2.如果存在一路径p1,p2,......pk,其中p1 为起点,pk