并没有什么想说的,但是要保持格式=w=
BZOJ1443传送门
看题可戳传送门
其实和 BZOJ2463 思路差不多
在棋盘上走,不染个色就亏了对吧 =w=
(思路来着Menci)
那么我们黑白染色一下,然后跑有效格子的最大匹配
假设我们一开始放在一个非匹配点上,那么先手要么就不能移动,要么移动到一个匹配点上,而后手可以沿着匹配边移动,这就是一个寻找增广路的过程,因为是最大匹配,所以最后一定停在一开始的一侧。所以我们可以知道,所有的非匹配点,如果作为起点,就是先手必败的
如果一开始放在最大匹配上呢?先手沿匹配边走,后手沿非匹配边走。如果后手走到一个非匹配点,先手就输了,而我们将这条路径取反,就是另一个最大匹配。所以不一定在最大匹配中的点,作为起点就是先手必败的
然后求不一定在最大匹配中的点,跑一遍Dinic之后,dfs打标记就好了
一些自己的思考:
在这个题里面的先手必胜和必败,都是对于 确定的局面 而言的
局面才是状态,而棋子位置不是
#include
#include
#include
using namespace std ;
bool inS[105*105] , Ppos[105*105] , vis[105*105] ;
char mp[105][105] ;
int N , M , tp = 1 , id[105][105] , id_c , head[105*105] , S , T , Ppos_cnt ;
struct Path{
int pre , to , flow ;
} p[105*105*6] ;
void In( int t1 , int t2 ){
p[++tp] = ( Path ){ head[t1] , t2 , 1 } ; head[t1] = tp ;
p[++tp] = ( Path ){ head[t2] , t1 , 0 } ; head[t2] = tp ;
}
void preWork(){
for( int i = 1 ; i <= N ; i ++ )
for( int j = 1 ; j <= M ; j ++ ) if( id[i][j] && ( ( i + j )&1 ) ){
if( id[i+1][j] ) In( id[i][j] , id[i+1][j] ) ;
if( id[i-1][j] ) In( id[i][j] , id[i-1][j] ) ;
if( id[i][j+1] ) In( id[i][j] , id[i][j+1] ) ;
if( id[i][j-1] ) In( id[i][j] , id[i][j-1] ) ;
In( S , id[i][j] ) , inS[ id[i][j] ] = true ;
} else if( id[i][j] ) In( id[i][j] , T ) ;
}
int dis[105*105] , que[105*105] , fr , ba ;
bool BFS(){
memset( dis , -1 , sizeof( dis ) ) ;
fr = 1 , que[ ba = 1 ] = S , dis[S] = 0 ;
while( ba >= fr ){
int u = que[fr++] ;
for( int i = head[u] ; i ; i = p[i].pre ){
int v = p[i].to ;
if( dis[v] != -1 || !p[i].flow ) continue ;
dis[v] = dis[u] + 1 , que[++ba] = v ;
}
} return dis[T] != -1 ;
}
int dfs_dinic( int u , int flow ){
if( u == T ) return flow ;
int rt = 0 ;
for( int i = head[u] ; i ; i = p[i].pre ){
int v = p[i].to , nowf ;
if( dis[v] != dis[u] + 1 || !p[i].flow ) continue ;
if( ( nowf = dfs_dinic( v , min( flow , p[i].flow ) ) ) ){
p[i].flow -= nowf ;
p[i^1].flow += nowf ;
flow -= nowf , rt += nowf ;
if( !flow ) break ;
}
} if( flow ) dis[u] = -1 ;
return rt ;
}
void dfs_solve( int u , int ef , bool sid ){
vis[u] = true ;
if( inS[u] == sid ) Ppos[u] = true , Ppos_cnt ++ ;
for( int i = head[u] ; i ; i = p[i].pre ){
int v = p[i].to ;
if( p[i].flow == ef && !vis[v] ) dfs_solve( v , ef , sid ) ;
}
}
void solve(){
while( BFS() ) dfs_dinic( S , 0x3f3f3f3f ) ;
dfs_solve( S , 1 , true ) ;
memset( vis , false , sizeof( vis ) ) ;
dfs_solve( T , 0 , 0 ) ;
puts( Ppos_cnt ? "WIN" : "LOSE" ) ;
for( int i = 1 ; i <= N ; i ++ )
for( int j = 1 ; j <= M ; j ++ )
if( Ppos[ id[i][j] ] ) printf( "%d %d\n" , i , j ) ;
}
int main(){
scanf( "%d%d" , &N , &M ) ;
for( int i = 1 ; i <= N ; i ++ ){
scanf( "%s" , mp[i] + 1 ) ;
for( int j = 1 ; j <= M ; j ++ )
if( mp[i][j] != '#' ) id[i][j] = ++id_c ;
} S = ++id_c , T = ++id_c ;
preWork() ; solve() ;
}