hdu4185+poj3020(最大匹配+最小边覆盖)

传送门:hdu4185 Oil Skimming

题意:n*n的方格里有字符*和#,只能在字符#上放1*2的板子且不能相交,求最多能放多少个。

分析:直接给#字符编号,然后相邻的可以匹配,建边后无向图跑匈牙利算法,最后得到的最大匹配数/2。

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-6
#define N 610
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PII pair<int,int>
using namespace std;
int match[N],vis[N],n,m,cnt;
int g[N][N],mat[N][N];
char s[N][N];
int dfs(int u)
{
    for(int i=1;i<=cnt;i++)
    {
        if(!vis[i]&&g[u][i])
        {
            vis[i]=1;
            if(match[i]==-1||dfs(match[i]))
            {
                match[i]=u;
                return 1;
            }
        }
    }
    return 0;
}
int hungary()
{
    memset(match,-1,sizeof(match));
    int ans=0;
    for(int i=1;i<=cnt;i++)
    {
        memset(vis,0,sizeof(vis));
        if(dfs(i))ans++;
    }
    return ans;
}
void judge(int i,int j)
{
    if(j+1<=n&&mat[i][j+1])
        g[mat[i][j]][mat[i][j+1]]=g[mat[i][j+1]][mat[i][j]]=1;
    if(i+1<=n&&mat[i+1][j])
        g[mat[i][j]][mat[i+1][j]]=g[mat[i+1][j]][mat[i][j]]=1;
}
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%s",s[i]+1);
        cnt=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
                if(s[i][j]==‘#‘)
                mat[i][j]=++cnt;
                else mat[i][j]=0;
        }
        FILL(g,0);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            if(mat[i][j])judge(i,j);
        int res=hungary();
        printf("Case %d: %d\n",cas++,res/2);
    }
}

传送门:poj 3020 Antenna Placement

题意:n*m的方格里有字符*和o,相邻的两个字符*可以连接,求覆盖完所有的*最少需要多少边。

分析:最少边覆盖所有点,就是最少边覆盖,最少边覆盖=总结点-最大匹配(双向图)/2。

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-6
#define N 410
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PII pair<int,int>
using namespace std;
int match[N],vis[N],n,m,cnt;
int g[N][N],mat[N][N];
char s[N][N];
int dfs(int u)
{
    for(int i=1;i<=cnt;i++)
    {
        if(!vis[i]&&g[u][i])
        {
            vis[i]=1;
            if(match[i]==-1||dfs(match[i]))
            {
                match[i]=u;
                return 1;
            }
        }
    }
    return 0;
}
int hungary()
{
    memset(match,-1,sizeof(match));
    int ans=0;
    for(int i=1;i<=cnt;i++)
    {
        memset(vis,0,sizeof(vis));
        if(dfs(i))ans++;
    }
    return ans;
}
void judge(int i,int j)
{
    if(j+1<=m&&mat[i][j+1])
        g[mat[i][j]][mat[i][j+1]]=g[mat[i][j+1]][mat[i][j]]=1;
    if(i+1<=n&&mat[i+1][j])
        g[mat[i][j]][mat[i+1][j]]=g[mat[i+1][j]][mat[i][j]]=1;
}
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%s",s[i]+1);
        cnt=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
                if(s[i][j]==‘*‘)
                mat[i][j]=++cnt;
                else mat[i][j]=0;
        }
        FILL(g,0);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            if(mat[i][j])judge(i,j);
        int res=hungary();
        printf("%d\n",cnt-res/2);
    }
}

时间: 2024-11-03 05:39:07

hdu4185+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)

题目:poj3020 题意:给出一个图,让你用最少的1*2的纸片覆盖掉图中的所有*出现过的地方.基本裸的最小边覆盖. 分析: 最小边覆盖 = 点总数 - 最大匹配 所以就是转化为求最大匹配. 跟前面一道题目很相似,也是相同的建图方法,奇偶性建图. #include <cstdio> #include <cstring> #include <string> #include <iostream> #include <algorithm> #incl

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

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

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

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

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

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

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

J - Air Raid - hdu 1151(最小边覆盖)

题意:给一个有向无环图,求出来最少需要几个士兵可以遍历所有的边. 分析:有向无环图的最小边覆盖 = 点数 - 最大匹配数 为什么是这样的公式??可以思考一下,如果这N个点之间没有边,是不是应该有N个士兵去查看,但是如果增加一条边就应该减去这条边,以此类推,公式就比较容易明白了. ******************************************************************** #include<stdio.h>#include<string.h>

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

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