2010年02月07日星期日.sgu190 二分图
2010年02月07日星期日.sgu190sgu190:
一开始想到的竟然是状态压缩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
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