二分图最大匹配 hdoj 1045

题目:hdoj1045

题意:给出一个图,其中有 . 和 X 两种,. 为通路,X表示墙,在其中放炸弹,然后炸弹不能穿过墙,问你最多在图中可以放多少个炸弹?

分析:这道题目是在上海邀请赛的题目的数据简化版,数据水了,所以有很多方法,这里讲二分图最大匹配,题目难点在于建图

想到用暴力过,但是事实证明我想多了。然后又想到多重二分匹配,后来发现没有办法表示图中的行列中墙的阻隔,后来看了别人的建图,瞬间觉得高大上。

建图,首先把每一行中的可以放一个炸弹的一块区域标记为同一个数字,数字不重复,然后列做相同的处理,即缩点!

缩点之后原图矩阵中每个点都对用一个行数字和一个列数字,然后按照这两个数字进行二分匹配,其相同值只取一个,得到的结果就是ans;

注意:每次判断增广的时候首先检查一下当前点有没有匹配,如果匹配就不用搜索,因为有多个值对应一个点,所以...

代码:

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10;
#define Del(x,y) memset(x,y,sizeof(x))
char map[N][N];
int path[N][N];
int line[N][N],row[N][N],link[N],vis[N],vlink[N];
int n,cnt_row,cnt_line;
bool dfs(int x)
{
    for(int i=0;i<cnt_line;i++)
    {
        if(path[x][i]==1 && vis[i]==0)
        {
            vis[i]=1;
            if(link[i]==-1 || dfs(link[i]))
            {
                link[i]=x;
                vlink[x]=i;
                return true;
            }
        }
    }
    return false;
}
void solve()
{
    int ans=0;
    Del(link,-1);
    Del(vlink,-1);
    for(int i=0;i<cnt_row;i++)
    {
        if(vlink[i]==-1){  ///注意!标记找过的
            Del(vis,0);
            if(dfs(i))
                ans++;
        }
    }
    printf("%d\n",ans);
}
int main()
{
    //freopen("Input.txt","r",stdin);
    while(~scanf("%d",&n) && n)
    {
        char c;
        Del(map,0);
        for(int i=0;i<n;i++)
        {
            getchar();
            for(int j=0;j<n;j++)
                scanf("%c",&map[i][j]);
        }
        Del(line,-1);
        Del(row,-1);
        cnt_row=0,cnt_line=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(map[i][j] == '.' && row[i][j] == -1)
                {
                    for(int k = j; map[i][k] == '.' && k < n; ++k)
                        row[i][k] = cnt_row;
                    cnt_row++;
                }
                if(map[j][i] == '.' && line[j][i] == -1)
                {
                    for(int k = j; map[k][i] == '.' && k < n; ++k)
                        line[k][i] = cnt_line;
                    cnt_line++;
                }
            }
        }
        Del(path,0);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(map[i][j]=='.')
                    path[row[i][j]][line[i][j]]=1;
            }
        }
        solve();
    }
    return 0;
}

二分图最大匹配 hdoj 1045

时间: 2024-08-10 13:42:22

二分图最大匹配 hdoj 1045的相关文章

HDU - 1045 Fire Net (二分图最大匹配-匈牙利算法)

(点击此处查看原题) 匈牙利算法简介 个人认为这个算法是一种贪心+暴力的算法,对于二分图的两部X和Y,记x为X部一点,y为Y部一点,我们枚举X的每个点x,如果Y部存在匹配的点y并且y没有被其他的x匹配,那就直接匹配:如果Y中已经没有可以和x匹配的点(包括可以匹配的点已经被其他的x匹配),那就让已经匹配的y的原配x'寻找其他可以匹配的y’,并将y和x匹配,最后,统计出匹配的对数 (详细了解的话,可以看看这位的博客:https://blog.csdn.net/sunny_hun/article/de

hdoj--1045&lt;dfs&amp;二分图最大匹配&gt;(这里是dfs解法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1045 题目描述: 在矩阵中放车,车可四面攻击,矩阵中有墙,可以防止攻击,给出墙的位置,输出最多可以放多少车: 题目要点:dfs&二分图最大匹配(匈牙利算法)(这里是dfs) 本题在一开始作的时候陷入了贪心的漩涡,写出来的以为是dfs.但实际上是谈心,而且贪心在这里是错误的:(贪心算法的应用范围比较窄,多数情况下是错误的) 然后发现了dfs与贪心的不同:贪心算法是每次放置车的方法都是固定,实际上并没有

ZOJ 1654 - Place the Robots (二分图最大匹配)

题意:在一个m*n的地图上,有空地,草和墙,其中空地和草能穿透攻击光线,而墙不能.每个机器人能够上下左右攻击,问在地图上最多能放多少个不互相攻击的机器人. 这个题和HDU 1045 -  Fire Net很像.很容易联想到对每个点编号然后互相攻击的点连边再求图的最大独立集,但是这个题数据量太多,超时. 换个思路. 将每个机器人可以攻击到的区域在横和竖方向上分开,这样当横和竖攻击方向都确定时就可以确定一个机器人的放置位置,而在同一个横或竖的攻击区域内不可以再放置机器人. 这样我们把原图上的空地按照

匈牙利算法dfs模板 [二分图][二分图最大匹配]

最近学了二分图最大匹配,bfs模板却死活打不出来?我可能学了假的bfs 于是用到了dfs模板 寻找二分图最大匹配的算法是匈牙利算法 匈牙利算法的主要程序是寻找增广路 寻找增光路是过程是:从一个未经配对的点出发,历经未配边.匹配边.未配边.匹配边.未配边....最终到达一个未配点的过程,只要把路径中的未配边和匹配边的“身份”对调,匹配就加一了.这就是一个寻找增广路的过程,通过不断寻找增广路,可以找到最大的匹配. 1 #include<cstdio> 2 #include<cstring&g

图论——LCA、强联通分量、桥、割顶、二分图最大匹配、网络流

A: 交通运输线 时间限制: 5 Sec  内存限制: 128 MB 题目描述 战后有很多城市被严重破坏,我们需要重建城市.然而,有些建设材料只能在某些地方产生.因此,我们必须通过城市交通,来运送这些材料的城市.由于大部分道路已经在战争期间完全遭到破坏,可能有两个城市之间没有道路.当然在运输线中,更不可能存在圈. 现在,你的任务来了.给你战后的道路情况,我们想知道,两个城市之间是否存在道路,如果存在,输出这两个城市之间的最短路径长度. 输入 第一行一个整数Case(Case<=10)表示测试数据

POJ 2226二分图最大匹配

匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法. #include<stdio.h> #include<string.h> #include<stdlib.h> int n1,n2; char map[1005][1005]; //数组开大点 int mapx[1005][1005],mapy[1005]

【Codevs1922】骑士共存问题(最小割,二分图最大匹配)

题意: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入. 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击. n<=200,m<=n^2 思路:经典的二分图最大匹配问题,采用黑白点染色的思想. 如果按照相邻点黑白不同染色,可以发现每次跳到的点必定与现在所在点不同色,二分图最大匹配即可. 这里用最小割来解决,因为不能允许任何黑白点之间的任何一条边有流量,符合最小割的思想. 1

POJ2239 Selecting Courses(二分图最大匹配)

题目链接 N节课,每节课在一个星期中的某一节,求最多能选几节课 好吧,想了半天没想出来,最后看了题解是二分图最大匹配,好弱 建图: 每节课 与 时间有一条边 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 #include <vector> 7 using namespa

二分图最大匹配总结

hdoj1528 二分匹配模版: 代码: 1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<algorithm> 5 #include<math.h> 6 using namespace std; 7 #define N 220 8 9 int n, maps[N][N], vis[N], used[N]; 10 11 struct node 12 {