hdu 3360 National Treasures 二分匹配

来源:互联网 发布:黄金直播软件 编辑:程序博客网 时间:2024/06/05 04:02

           题意:给出一个R*C的表,每个格子上标有值,-1表示已经有的保安,其他表示古董的价值,要看守一个古董就必须在1~12各个点上都有保安,求最少要雇的保安。

           思路:建图,从图中可以发现古董和保安的位置相差一个奇数,所以我们可以将表格着色,白的为x部,黑的为Y部,古董和保安连一条边,求最小点覆盖。

          代码:

    

#include<stdio.h>#include<string.h>#include<algorithm>#define maxn 52#define clr(a,b) memset(a,b,sizeof(a))using namespace std;int px[]={-1,-2,-2,-1,1,2,2,1,-1,0,1,0};int py[]={-2,-1,1,2,2,1,-1,-2,0,1,0,-1};int map[maxn][maxn],vis[10000];int mat[maxn*maxn],nx,ny,r,c,id[maxn][maxn];int first[1000],ev[20001],next[20001],e;bool find(int u){    int v;    for(int i=first[u];i!=-1;i=next[i])    {        v=ev[i];        if(!vis[v])        {            vis[v]=1;            if(mat[v]==-1||find(mat[v]))            {                mat[v]=u;                return 1;            }        }    }    return 0;}int Hungary(int nx){    clr(mat,-1);    int Max=0;    for(int i=1;i<=nx;i++)    {        clr(vis,0);        if(find(i))           Max++;    }    return Max;}void add(int u,int v){    next[e]=first[u],ev[e]=v,first[u]=e++;}void makemap(){    int x,k,u,v;    clr(first,-1);    e=1;   for(int i=1;i<=r;i++)      for(int j=1;j<=c;j++)    {        if(map[i][j]==-1) continue;        x=map[i][j];        k=0;        while(x)        {            if(x%2==1)            {                u=i+px[k];                v=j+py[k];                if(1<=u&&u<=r&&v>=1&&v<=c&&map[u][v]!=-1)                  {                       if((i+j)%2==0)                       add(id[i][j],id[u][v]);                       else                       add(id[u][v],id[i][j]);                  }            }            k++;            x/=2;        }    }}int main(){    //freopen("D:/d.txt","r",stdin);    int cas=1,ans;    while(~scanf("%d %d",&r,&c))    {        if(r==c&&r==0)          break;        clr(id,0);        nx=0;        ny=0;        for(int i=1;i<=r;i++)           for(int j=1;j<=c;j++)             {                 scanf("%d",&map[i][j]);                 if(map[i][j]==-1) continue;                 else if((i+j)%2==0) id[i][j]=++nx;                 else id[i][j]=++ny;             }        makemap();        ans=Hungary(nx);        printf("%d. %d\n",cas++,ans);    }    return 0;}