hdu1507--二分图最大匹配

题意:你大爷,哦不!你大叔继承了一块地什么的都是废话。。,这里说说题意,和怎么建图。

题意:这里有一块N*M的地,但是有 K 个地方,是池塘,然后输入K行(x,y),OK,现在可以出售的地必须是 1*2 大小的矩形,并且不能是池塘。。。问,在N*M的这块地上,能有多少块地可以出售,并且,要输出这些可以出售的地的坐标。

建图:那么这里其实和我之前做过的hdu4185 差不多1A。。http://blog.csdn.net/zyy173533832/article/details/12654539

那么可以预先处理一下,把N*M的地图中,是土地的按 1,2,3....编号,在这里我们需要对于每个编号,记录这个编号的土地的坐标。那么这里他说了N*M-K <= 50,那么我们接着对于每个土地,遍历四个方向,看看有木有可以组在一起变成能卖的地,然后。。。然后图就建好啦。

那么在二分匹配的过程中也要注意的是:匹配好的数量需要÷2,输出的时候也有点需要注意的,直接看代码中的解释:

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

#define MAX 105

int N,M,K;
int map[MAX][MAX];
int loc[MAX/2][2];//这里是根据编号记录坐标   如第2个地的坐标 (loc[2][0] , loc[2][1])
int node_num; //点数,也就是土地的数量,编号的那个

struct Edge{//邻接表
    int to,next;
}edge[MAX*4];
int head[MAX/2],edge_num;

void add(int u,int v){
    edge[edge_num].to = v;
    edge[edge_num].next = head[u];
    head[u] = edge_num++;
}

int vis[4][2]={0,1,0,-1,1,0,-1,0};

void initMap(){
    node_num = 1;
    memset(map,0,sizeof(map));

    int x,y;
    while(K --){
        cin >> x >> y;
        map[x][y] = -1;//表示此地不可用,是池塘
    }

    for(int i = 1; i <= N; i ++){
        for(int j = 1; j <= M; j ++){
            if(!map[i][j]) {
                 map[i][j] = node_num++;
                 loc[node_num-1][0] = i; loc[node_num-1][1] = j;//记录坐标
            }
        }
    }

    edge_num = 0;
    memset(head,-1,sizeof(head));
    for(int i = 1; i <= N; i ++){
        for(int j = 1; j <= M; j ++){
            if(map[i][j] != -1){
                for(int k = 0; k < 4; k ++)
                {
                    int x = i+vis[k][0],y = j+vis[k][1];
                    if(map[x][y] != -1 && x >=1 && y >= 1 && x <= N && y <= M)
                    {
                        add(map[i][j],map[x][y]); add(map[x][y],map[i][j]);
                    }
                }
            }
        }
    }
}
//------------------------
bool useif[MAX/2];
int link[MAX/2];
bool dfs(int u){
    for(int i = head[u]; i != -1; i = edge[i].next){
        int v = edge[i].to;
        if(!useif[v]){
            useif[v] = true;
            if(link[v] == -1 || dfs(link[v]))
            {
                link[v] = u;
                return true;
            }
        }
    }
    return false;
}
void match(){
    int ans_num = 0;
    memset(link,-1,sizeof(link));
    for(int i = 1; i <= node_num; i ++){
        memset(useif,false,sizeof(useif));
        if(dfs(i)) ans_num++;
    }

    //print
    cout << ans_num/2 <<endl;
    bool ifmatch[MAX/2]={false}; //这里是表示这个点是不是被输出过
    for(int i = 1; i <= node_num; i ++){
        if(!ifmatch[i] && link[i] != -1 && !ifmatch[link[i]]){
            ifmatch[i] = true; ifmatch[link[i]] = true;
            printf("(%d,%d)--(%d,%d)\n",loc[i][0],loc[i][1],loc[link[i]][0],loc[link[i]][1]);
        }
    }
}

int main()
{
    bool first_cas = true;//控制案例间空行
    while(cin >> N >> M)
    {
        if(!N && !M) break;
        cin >> K;
        initMap();
        if(!first_cas) cout << endl;
        match();
        first_cas = false;
    }
    return 0;
}

个人愚昧观点,欢迎指正与讨论

hdu1507--二分图最大匹配,布布扣,bubuko.com

时间: 2024-10-12 16:41:58

hdu1507--二分图最大匹配的相关文章

匈牙利算法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 {

POJ - 1422 Air Raid 二分图最大匹配

题目大意:有n个点,m条单向线段.现在问要从几个点出发才能遍历到所有的点 解题思路:二分图最大匹配,只要一条匹配,就表示两个点联通,两个点联通只需要选取其中一个点即可,所以有多少条匹配,就可以减去多少个点 #include<cstdio> #include<cstring> using namespace std; const int N = 130; int g[N][N], vis[N], link[N]; int n, m; void init() { memset(g, 0

&quot;《算法导论》之‘图’&quot;:不带权二分图最大匹配(匈牙利算法)

博文“二分图的最大匹配.完美匹配和匈牙利算法”对二分图相关的几个概念讲的特别形象,特别容易理解.本文介绍部分主要摘自此博文. 还有其他可参考博文: 趣写算法系列之--匈牙利算法 用于二分图匹配的匈牙利算法 1. 前言 二分图:简单来说,如果图中点可以被分为两组,并且使得所有边都跨越组的边界,则这就是一个二分图.准确地说:把一个图的顶点划分为两个不相交集 U 和V ,使得每一条边都分别连接U.V中的顶点.如果存在这样的划分,则此图为一个二分图.二分图的一个等价定义是:不含有「含奇数条边的环」的图.

[HDU] 2063 过山车(二分图最大匹配)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2063 女生为X集合,男生为Y集合,求二分图最大匹配数即可. 1 #include<cstdio> 2 #include<iostream> 3 #include<string.h> 4 #include<algorithm> 5 #include<math.h> 6 #include<stdbool.h> 7 #include<ti

hihoCoder #1122 : 二分图二?二分图最大匹配之匈牙利算法

#1122 : 二分图二•二分图最大匹配之匈牙利算法 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 上一回我们已经将所有有问题的相亲情况表剔除了,那么接下来要做的就是安排相亲了.因为过年时间并不是很长,所以姑姑希望能够尽可能在一天安排比较多的相亲.由于一个人同一天只能和一个人相亲,所以要从当前的相亲情况表里选择尽可能多的组合,且每个人不会出现两次.不知道有没有什么好办法,对于当前给定的相亲情况表,能够算出最多能同时