杭电 hdu Warm up 2 (二分匹配)

来源:互联网 发布:考研网络辅导班 编辑:程序博客网 时间:2024/04/30 17:39

杭电  hdu  Warm up 2 (二分匹配)




Warm up 2

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1991    Accepted Submission(s): 904


Problem Description
  Some 1×2 dominoes are placed on a plane. Each dominoe is placed either horizontally or vertically. It's guaranteed the dominoes in the same direction are not overlapped, but horizontal and vertical dominoes may overlap with each other. You task is to remove some dominoes, so that the remaining dominoes do not overlap with each other. Now, tell me the maximum number of dominoes left on the board.
 

Input
  There are multiple input cases.
  The first line of each case are 2 integers: n(1 <= n <= 1000), m(1 <= m <= 1000), indicating the number of horizontal and vertical dominoes.
Then n lines follow, each line contains 2 integers x (0 <= x <= 100) and y (0 <= y <= 100), indicating the position of a horizontal dominoe. The dominoe occupies the grids of (x, y) and (x + 1, y).
  Then m lines follow, each line contains 2 integers x (0 <= x <= 100) and y (0 <= y <= 100), indicating the position of a horizontal dominoe. The dominoe occupies the grids of (x, y) and (x, y + 1).
  Input ends with n = 0 and m = 0.
 

Output
  For each test case, output the maximum number of remaining dominoes in a line.
 

Sample Input
2 30 00 30 11 11 34 50 10 23 12 20 01 02 04 13 20 0
 

Sample Output
46
 

Author
SYSU
 

Source
2013 Multi-University Training Contest 2
 

Recommend
zhuyuanchen520   |   We have carefully selected several similar problems for you:  5283 5282 5281 5280 5279 
 









题意:在矩形格子中,有很多1*2的骨牌,有一些事水平放置,也就是给你坐标(x, y),而它是(x, y)到(x + 1, y),要是是竖直放置,那就表明,如果它给你点(x, y), 
而它是(x, y)到(x, y + 1); 
相同方向不会有叠加的情况发生,也就是都是水平的或者都是竖直的,这些骨牌不会相互叠加,只有一水平,一竖直的可能会叠加
然后给你n,m,表示水平的有n个骨牌,竖直的有m个骨牌
接下来是n个坐标,代表水平的骨牌
然后是m个坐标,代表竖直的骨牌
问,最多能有多少骨牌,要是叠加就要舍弃一些,使其不叠加






题解:二分匹配,然后将所有的骨牌数减去最大匹配数(n + m) - p
令水平的骨牌为x,竖直的骨牌为y
通过将所有的点都放进结构体中,然后两个for循环进行遍历,找出与水平相交的竖直的骨牌,然后map[xi][yi] = 1,最后就可以轻松的二分匹配进行求解







#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <algorithm>#include <iostream>using namespace std;const int maxn = 1005;int map[maxn][maxn];                //匹配,0表示没有连接,1表示有连接int vis[maxn];int pri[maxn];                  //pri[i] = x;表示x骨牌和i骨牌匹配int n, m;struct node{                   //用来放骨牌的坐标    int x, y;};node hor[maxn], ver[maxn];void Init (){    int i, j;    memset (map, 0, sizeof (map));    memset (pri, -1, sizeof (pri));    for (i = 1; i <= n; ++i)        scanf ("%d%d", &hor[i].x, &hor[i].y);    for (i = 1; i <= m; ++i)        scanf ("%d%d", &ver[i].x, &ver[i].y);    for (i = 1; i <= n; ++i){        for (j = 1; j <= m; ++j){           //查找水平和竖直的骨牌,哪些是有叠加的            if ((hor[i].y == ver[j].y || hor[i].y == ver[j].y + 1) && (hor[i].x == ver[j].x || hor[i].x == ver[j].x - 1))                map[i][j] = 1;                          //将他们匹配,连接起来        }    }}bool Find (int x){                     //寻找匹配    int i;    for (i = 1; i <= m; ++i){        if (!vis[i] && map[x][i]){            vis[i] = 1;            if (pri[i] == -1 || Find (pri[i])){           //进行最大匹配数的遍历                pri[i] = x;                return true;            }        }    }    return false;}int main (){    int i;    while (scanf ("%d%d", &n, &m) != EOF){        if (n == 0 && m == 0) break;        Init();        int ant = 0;        for (i = 1; i <= n; ++i){            memset (vis, 0, sizeof (vis));            if (Find (i))                ant++;        }        printf ("%d\n", n + m - ant);    }    return 0;}


0 0