zoukankan      html  css  js  c++  java
  • [POJ] 2446 Chessboard(二分图最大匹配)

    题目地址:http://poj.org/problem?id=2446

    本题建图是关键。因为卡片都是1*2,所以若点V被某个1*2卡片覆盖,则周围包含V的其它1*2区域都不成立。所以想到只要把V点划分在X集合,周围点在Y集合,V向周围点分别连边,就变成了二分图匹配问题,区分点V与周围点可以用横纵坐标之和的奇偶性。若棋盘上除障碍外都能被1*2卡片覆盖,则最大匹配数ans=(棋盘所有点数n*m-障碍数k)/2。本题在进行之前还有一个小优化,如果n*m-k是奇数,显而易见是不成立的,所以直接返回NO。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<string.h>
      4 #include<algorithm>
      5 #include<math.h>
      6 #include<stdbool.h>
      7 #include<time.h>
      8 #include<stdlib.h>
      9 #include<set>
     10 #include<map>
     11 #include<stack>
     12 #include<queue>
     13 #include<vector>
     14 using namespace std;
     15 #define clr(x,y)    memset(x,y,sizeof(x))
     16 #define sqr(x)      ((x)*(x))
     17 #define rep(i,a,b)  for(int i=(a);i<=(b);i++)
     18 #define LL          long long
     19 #define INF         0x3f3f3f3f
     20 #define A           first
     21 #define B           second
     22 #define PI          3.14159265358979323
     23 const int N=2000+11;
     24 const int dx[4]={0,0,1,-1};
     25 const int dy[4]={1,-1,0,0};
     26 int n,m,k1,k,k2,f[N],g[N][N],link[N],flag[N][N],a[N],b[N];
     27 
     28 void init()
     29 {
     30     clr(f,0);
     31     clr(g,0);
     32     clr(flag,0);
     33     clr(a,0);
     34     clr(b,0);
     35     clr(link,-1);
     36     k1=0;
     37     k2=0;
     38 }
     39 
     40 bool find(int x)
     41 {
     42     for(int i=0;i<k2;i++) {
     43         if(!f[b[i]] && g[x][b[i]]) {
     44             f[b[i]]=1;
     45             if(link[b[i]]==-1 || find(link[b[i]])) {
     46                 link[b[i]]=x;
     47                 return true;
     48             }
     49         }
     50     }
     51     
     52     return false;
     53 }
     54 
     55 int hungary()
     56 {
     57     int ans=0;
     58     for(int i=0;i<k1;i++) {
     59         clr(f,0);
     60         if(find(a[i])) ans++;
     61     }
     62     return ans;
     63 }
     64 
     65 int main()
     66 {
     67     int u,v,x,y;
     68     
     69     init(); 
     70     scanf("%d%d%d",&m,&n,&k);
     71     if((m*n-k)&1) {
     72         printf("NO
    ");
     73         return 0;
     74     }
     75     for(int i=1;i<=m;i++) {
     76         for(int j=1;j<=n;j++) 
     77         flag[i][j]=1;
     78     }
     79     for(int i=1;i<=k;i++) {
     80         scanf("%d%d",&y,&x);
     81         flag[x][y]=0;
     82     }
     83 
     84     for(int i=1;i<=m;i++) {
     85         for(int j=1;j<=n;j++) {
     86             
     87             int p=(i-1)*n+j;
     88             if((i+j)&1) {
     89                 if(flag[i][j]) a[k1++]=p;
     90             }  else {
     91                 if(flag[i][j]) b[k2++]=p;
     92             }   
     93         }
     94     }
     95     
     96     for(int i=1;i<=m;i++) {
     97         for(int j=1;j<=n;j++) {
     98             if(flag[i][j])
     99             for(int k=0;k<4;k++) {
    100                 int nx=i+dx[k];
    101                 int ny=j+dy[k];
    102                 if(flag[nx][ny]) {
    103                     g[(i-1)*n+j][(nx-1)*n+ny]=1;
    104                 }
    105             }
    106         }
    107     }
    108    
    109    if(2*hungary()+k==n*m) printf("YES
    ");
    110    else  printf("NO
    ");
    111     
    112     return 0;
    113 }
  • 相关阅读:
    PHP编程基础学习(一)——数据类型
    6-6 带头结点的链式表操作集(20 分)
    6-5 链式表操作集(20 分)
    6-4 链式表的按序号查找(10 分)
    6-3 求链式表的表长(10 分)
    6-2 顺序表操作集(20 分)
    6-1 单链表逆转(20 分)
    学生成绩管理系统(六):项目总结
    学生成绩管理系统(五):系统的完善与数据库的链接
    学生成绩管理系统(四)
  • 原文地址:https://www.cnblogs.com/sxiszero/p/4378563.html
Copyright © 2011-2022 走看看