现在的位置: 首页 > 综合 > 正文

hdu4619Warm up 2(二分匹配)

2013年10月25日 ⁄ 综合 ⁄ 共 1822字 ⁄ 字号 评论关闭

题目请戳这里

题目大意:给一些1*2的多米诺骨牌,放到一个棋盘中,n个横着放,m个竖着放,同向的牌不会有交叉,现在要拿掉一些骨牌保证每个格子最多被一个骨牌占领,求剩下最多骨牌数量。

题目分析:裸的二分匹配,经典的染色模型。对格子黑白染色,每张多米诺骨牌必占一黑一白2个格子,从白格子向黑格子建边,跑一下匈牙利即可。

骨牌坐标范围0-100,所以棋盘102*102,黑白点最多5202个,边不超过2000条,匈牙利复杂度是O(m*n),够了。

详情请见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<string>
using namespace std;
const int N = 5203;
const int M = 40005;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const double PI = acos(-1.0);
typedef __int64 ll;
//#pragma comment(linker, "/STACK:1024000000,1024000000")

struct node
{
    int to,next;
}edge[M];
int num,n,m;
int head[N];
bool flag[N];
int cx[N],cy[N];
int nn,mm;
void build(int s,int e)
{
    edge[num].to = e;
    edge[num].next = head[s];
    head[s] = num++;
}

int path(int cur)
{
    int i;
    for(i = head[cur];i != -1;i = edge[i].next)
    {
        if(flag[edge[i].to] == false)
        {
            flag[edge[i].to] = true;
            if(cy[edge[i].to] == -1 || path(cy[edge[i].to]))
            {
                cy[edge[i].to] = cur;
                cx[cur] = edge[i].to;
                return 1;
            }
        }
    }
    return 0;
}

int maxmatch()
{
    memset(cx,-1,sizeof(cx));
    memset(cy,-1,sizeof(cy));
    int i,ret;
    for(ret = 0,i = 1;i <= 5202;i ++)
        if(cx[i] == -1)
        {
            memset(flag,false,sizeof(flag));
            ret += path(i);
        }
    return ret;
}

int main()
{
    int a,b;
    //freopen("1009.in","r",stdin);
    //freopen("data.out","w",stdout);
    while(scanf("%d%d",&nn,&mm),(nn + mm))
    {
        num = 0;
        memset(head,-1,sizeof(head));
        while(nn --)//横向牌
        {
            scanf("%d%d",&a,&b);
            if((a+b)&1)//起点是黑点
            {
                if(b&1)
                    build(b*51+1+(a>>1),b*51+1+(a>>1));
                else
                    build(b*51+1+((a+1)>>1),b*51+((a+1)>>1));
            }
            else
            {
                if(b&1)
                    build(b*51+((a+1)>>1),b*51+1+((a+1)>>1));
                else
                    build(b*51+1+(a>>1),b*51+1+(a>>1));
            }
        }
        while(mm --)
        {
            scanf("%d%d",&a,&b);
            if((a+b)&1)
            {
                if(b&1)
                    build(b*51+52+(a>>1),b*51+1+(a>>1));
                else
                    build(b*51+51+((a+1)>>1),b*51+((a+1)>>1));
            }
            else
            {
                if(b&1)
                    build(b*51+((a+1)>>1),b*51+51+((a+1)>>1));
                else
                    build(b*51+((a>>1)+1),b*51+1+51+((a>>1)));
            }
        }
        printf("%d\n",maxmatch());
    }
    return 0;
}
//15MS	332K

抱歉!评论已关闭.