zoukankan      html  css  js  c++  java
  • 【JSOI 2009】游戏 Game

      http://www.zybbs.org/JudgeOnline/problem.php?id=1443

      此题竟然被改造出现在NOI2011的赛场上……

      半年前qz神牛在回宿舍的路上跟我吐槽这道题的捉法,但是被我忘干净了。NOI出现这道题我庆幸自己只是参加了同步赛,要不然就挂了。

      膜拜过qz和CLJ的题解之后搞定了这个题。

    ------------------------------Clavichord Orz----------------------------WJMZBMR Orz----------------------------------------

      我们想象棋盘被黑白染色,那么黑格的棋子只能往相邻的白格走,白格的棋子只能往相邻的黑格走。

      当对方走到一个白格(或黑格)时,如果上下左右有合法的黑格(或白格),那么我们就可以移动到这个格子。

      每个格子只能被经过一次。到这里我们可以想到二分图最大匹配。

      当先手将棋子放置在“一定是”最大匹配的格子时,后手可以顺着最大匹配走,一定是先手必败。

      当先手将棋子放置在其他位置时(不一定是最大匹配的格子),先手就可以顺着后手的最大匹配走,从而先手获胜。

      问题转化为在一个二分图中判断某点是否可以不在最大匹配中。

      我在求最大匹配的过程中使用sap增广,对于“一定在最大匹配中”的判断我使用的类似判断割边的方法,从源点和汇点分别进行dfs判断。程序跑到了624MS,惊讶…………

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #define inf 2147483647
    #define num(i,j) ((i)*m+(j))
    #define mm 400000
    using namespace std;
    
    int n,m,d[10010],vd[10010],map[101][101],source,sink;
    bool vis[10010],match[10010];
    
    struct EDGE{
    	int pnt,cap;
    	EDGE *pre,*ref;
    	EDGE(){}
    	EDGE(int _pnt,int _cap,EDGE *_pre):pnt(_pnt),cap(_cap),pre(_pre){}
    }Edge[mm*2],*SP=Edge,*edge[mm];
    
    inline void addedge(int a,int b){
    	edge[a]=new(++SP)EDGE(b,1,edge[a]);
    	edge[b]=new(++SP)EDGE(a,0,edge[b]);
    	edge[a]->ref=edge[b],edge[b]->ref=edge[a];
    }
    
    int sap(int i,int flow){
    	if(i==sink) return flow;
    	int cur=0;
    	for(EDGE *j=edge[i];j;j=j->pre)
    		if(j->cap&&d[i]-d[j->pnt]==1){
    			int tmp=sap(j->pnt,min(flow-cur,j->cap));
    			j->ref->cap+=tmp,j->cap-=tmp,cur+=tmp;
    			if(cur==flow) return cur;
    		}
    	if(!(--vd[d[i]])) d[source]=sink+1;
    	if(d[source]>sink+1) return cur;
    	vd[++d[i]]++;
    	return cur;
    }
    
    void dfs(int i,int flag){
    	vis[i]=true;
    	if(((i%m+i/m)&1)==flag) match[i]=true;
    	for(EDGE *j=edge[i];j;j=j->pre)
    		if(j->cap==flag&&!vis[j->pnt]) dfs(j->pnt,flag);
    }
    
    int main(){
    	freopen("game.in","r",stdin);
    	freopen("game.out","w",stdout);
    	scanf("%d%d",&n,&m);getchar();
    	for(int i=0;i<n;i++,getchar())
    		for(int j=0;j<m;j++)
    			map[i][j]=getchar()=='.';
    	source=n*m,sink=source+1;
    	for(int i=0;i<n;i++)
    		for(int j=0;j<m;j++)
    			if(map[i][j])
    				if((i+j)&1){
    					addedge(source,num(i,j));
    					if(i&&map[i-1][j]) addedge(num(i,j),num(i-1,j));
    					if(j&&map[i][j-1]) addedge(num(i,j),num(i,j-1));
    					if(i<n-1&&map[i+1][j]) addedge(num(i,j),num(i+1,j));
    					if(j<m-1&&map[i][j+1]) addedge(num(i,j),num(i,j+1));
    				}else addedge(num(i,j),sink);
    	vd[0]=sink+1;
    	while(d[source]<sink+1) sap(source,inf);
    	memset(vis,false,sizeof(vis));dfs(source,1);
    	memset(vis,false,sizeof(vis));dfs(sink,0);
    	bool Win_Chance=false;
    	for(int i=0;i<n*m;i++)
    		if(match[i]){
    			Win_Chance=true;
    			break;
    		}
    	if(Win_Chance){
    		printf("WIN\n");
    		for(int i=0;i<n*m;i++)
    			if(match[i]) printf("%d %d\n",(i/m)+1,(i%m)+1);
    	}else printf("LOSE\n");
    	return 0;
    }
    
  • 相关阅读:
    使用Docker-compose部署MySQL测试环境
    使用MySQL SQL线程回放Binlog实现恢复
    MySQL 插件之 连接控制插件(Connection-Control)
    sysbench工具使用
    故障分析--主从复制故障1
    MySQL性能指标计算方式
    AJAX的 同步异步;EZView.js 图片预览和pdf预览
    Caused by: java.lang.ClassNotFoundException: org.springframework.context.App
    解决Myeclipse或Eclipse出现JPA project Change Event Handler问题的解决办法
    java中转换为string的方法;eques和==区别
  • 原文地址:https://www.cnblogs.com/Delostik/p/2137712.html
Copyright © 2011-2022 走看看