2010年02月07日星期日.sgu190 二分图

2010年02月07日星期日.sgu190 二分图

2010年02月07日星期日.sgu190
sgu190:
一开始想到的竟然是状态压缩dp,然后一看n,貌似大了点。
然后怎么想也没思路,上网看看,才知道原来二分图还可以这么用,我怎么从来也没想到呢。。。。

将图像国际象棋棋盘那样黑白染色,然后给对于每个颜色给每个格子一个编号。
然后选一个染色,对每个格子和他旁边的格子建边,这样构成一个二分图。
求出最大的匹配数,然后再按照题目的猥琐要求输出即可。

注意 题目中棋盘的格式是这个样子的。
(2,1) (2,2)
(1,1) (1,2)
左下角是(1,1)
如果按照平常的左上角是(1,1)来搞,需要注意一下输出

  1 
  2  int  g[ 801 ][ 801 ],n,P;
  3  const   int  BLACK  =   1 ;
  4  const   int  WHITE  =   2 ;
  5  const   int  REMOVED  =   3 ;
  6  int  num[ 41 ][ 41 ],bsp,wsp,cnt;
  7  int  board[ 41 ][ 41 ];
  8  int  bcoord[ 41 * 41 ][ 2 ];
  9  int  wcoord[ 41 * 41 ][ 2 ];
 10  int  vis[ 801 ];
 11  int  L[ 801 ],R[ 801 ];
 12 
 13  bool  make_graph()
 14  {
 15     int  i,j;cnt  =   0 ;
 16     for  (i  =   1 ;i  <=  n;i ++ ) {
 17         for  (j  =   1 ;j  <=  n;j ++ ) {
 18             if  (board[i][j]  !=  REMOVED) {
 19                cnt  ++ ;
 20                 if  ((i + j) % 2 == 1 ) {
 21                    board[i][j]  =  WHITE;
 22                    wcoord[wsp][ 0 =  i, wcoord[wsp][ 1 =  j;
 23                    num[i][j]  =  wsp ++ ;
 24                } else  {
 25                    board[i][j]  =  BLACK;
 26                    bcoord[bsp][ 0 =  i, bcoord[bsp][ 1 =  j;
 27                    num[i][j]  =  bsp ++ ;
 28                }
 29            }
 30        }
 31    }
 32     for  (i  =   1 ;i  <=  n;i ++ ) {
 33         for  (j  =   1 ;j  <=  n;j ++ ) {
 34             if  (board[i][j]  ==  BLACK) {
 35                 if  (board[i + 1 ][j]  ==  WHITE) g[num[i][j]][num[i + 1 ][j]]  =   1 ;
 36                 if  (board[i][j + 1 ==  WHITE) g[num[i][j]][num[i][j + 1 ]]  =   1 ;
 37                 if  (board[i - 1 ][j]  ==  WHITE) g[num[i][j]][num[i - 1 ][j]]  =   1 ;
 38                 if  (board[i][j - 1 ==  WHITE) g[num[i][j]][num[i][j - 1 ]]  =   1 ;
 39            }
 40        }
 41    }
 42     return   true ;
 43  }
 44 
 45  bool  dfs( int  u) {
 46     for  ( int  v  =   0 ;v  <  wsp;v ++ ) {
 47         if  (g[u][v]  &&   ! vis[v]) {
 48            vis[v]  =   true ;
 49             if  (R[v]  ==   - 1   ||  dfs(R[v])) {
 50                L[u]  =  v;
 51                R[v]  =  u;
 52                 return   true ;
 53            }
 54        }
 55    }
 56     return   false ;
 57  }
 58 
 59  int  MaxMatch()
 60  {
 61     int  i,res  =   0 ;
 62    memset(L, - 1 , sizeof (L));
 63    memset(R, - 1 , sizeof (R));
 64 
 65     for  (i  =   0 ;i  <  bsp;i ++ ) {
 66         if  (L[i]  ==   - 1 ) {
 67            memset(vis, 0 , sizeof (vis));
 68             if  (dfs(i)) {
 69                res ++ ;
 70            }
 71        }
 72    }
 73     return  res;
 74  }
 75 
 76  int   out [ 801 ][ 2 ],top;
 77  bool  proc()
 78  {
 79    make_graph();  if  (cnt  &   1 ) {  return   false ; }
 80     if  (bsp  ==   0   ||  wsp  ==   0 ) {  return   false ; }
 81     if  (bsp  !=  wsp) {  return   false ; }
 82     return  (MaxMatch()  *   2   ==  cnt);
 83  }
 84 
 85  int  main()
 86  {
 87     int  i,j,k,a,b;
 88    scanf( " %d%d " , & n, & P);
 89     for  (i  =   0 ;i  <  P;i ++ ) {
 90        scanf( " %d%d " , & a, & b);
 91        board[a][b]  =  REMOVED;
 92    }
 93     if  (proc()) {
 94        printf( " Yes\n " );
 95        top  =   0 ;
 96         for  (i  =   0 ;i  <  bsp;i ++ ) {
 97             if  (bcoord[i][ 1 ==  wcoord[L[i]][ 1 ]) {
 98                 if  (bcoord[i][ 0 <  wcoord[L[i]][ 0 ]) {
 99                     out [top][ 0 =  bcoord[i][ 0 ];
100                     out [top][ 1 =  bcoord[i][ 1 ];
101                    top ++ ;
102                } else  {
103                     out [top][ 0 =  wcoord[L[i]][ 0 ];
104                     out [top][ 1 =  wcoord[L[i]][ 1 ];
105                    top ++ ;
106                }
107            }
108        }
109 
110        printf( " %d\n " ,top);
111         for  (i  =   0 ;i  <  top;i ++ ) { printf( " %d %d\n " , out [i][ 0 ], out [i][ 1 ]); }
112 
113        top  =   0 ;
114         for  (i  =   0 ;i  <  bsp;i ++ ) {
115             if  (bcoord[i][ 0 ==  wcoord[L[i]][ 0 ]) {
116                 if  (bcoord[i][ 1 <  wcoord[L[i]][ 1 ]) {
117                     out [top][ 0 =  bcoord[i][ 0 ];
118                     out [top][ 1 =  bcoord[i][ 1 ];
119                    top ++ ;
120                } else  {
121                     out [top][ 0 =  wcoord[L[i]][ 0 ];
122                     out [top][ 1 =  wcoord[L[i]][ 1 ];
123                    top ++ ;
124                }
125            }
126        } // http://www.cppblog.com/schindlerlee
127        printf( " %d\n " ,top);
128         for  (i  =   0 ;i  <  top;i ++ ) { printf( " %d %d\n " , out [i][ 0 ], out [i][ 1 ]); }
129    } else  {
130        printf( " No\n " );
131    }
132 
133 
134     return   0 ;
135  }
136 
137 

你可能感兴趣的:(2010年02月07日星期日.sgu190 二分图)