zoukankan      html  css  js  c++  java
  • BZOJ1443 [JSOI2009]游戏Game

    题目大意:

    一张网格图,有一些格子不可走,以某一格子为起点,两个人轮流移动,要求:只能移动到相邻的格子,走过的格子不能重复走。

    问哪些格子后手必胜



    考虑对网格图进行二分图染色

    如果一个起点是二分图最大匹配中的必要点,那么先手就可以每次走匹配边,后手只能走非匹配边,由于最大匹配不存在增广路,所以后手必败

    如果起点是二分图最大匹配中的非必要点,那么先手只能走一条非匹配边(或可以视作非匹配边的匹配边),后手就可以重复上述情况

    注意二分图最大匹配中任意一条边的两个顶点至少有一个在匹配中,否则会出现新的最大匹配

    所以我们只要找出所有的最大匹配中的非必要点

    一个很(naive)的想法是先跑一遍最大匹配,然后删除每个节点再跑一遍,不过有点慢

    其实我们只要求出最大匹配后寻找交错路

    对于不在最大匹配中的点,必定是非必须点,我们通过这些不在最大匹配中的点进行(dfs),如果能遇到颜色相同的节点说明该节点也是非必须点

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    namespace red{
    #define int long long
    #define eps (1e-8)
    	inline int read()
    	{
    		int x=0;char ch,f=1;
    		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    		if(ch=='-') f=0,ch=getchar();
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    		return f?x:-x;
    	}
    	const int N=410;
    	int n,m,num,tot,idx;
    	char s[N][N];
    	int g[N*N],id[N][N];
    	int f[N*N];
    	bool vis[N*N];
    	bool ans[N*N];
    	int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
    	int head[N*N],cnt;
    	struct point
    	{
    		int nxt,to;
    		point(){}
    		point(const int &nxt,const int &to):nxt(nxt),to(to){}
    	}a[N*N];
    	inline void link(int x,int y)
    	{
    		a[++cnt]=(point){head[x],y};head[x]=cnt;
    	}
    	inline bool find(int x)
    	{
    		for(int i=head[x];i;i=a[i].nxt)
    		{
    			int t=a[i].to;
    			if(vis[t]) continue;
    			vis[t]=1;
    			if(!f[t]||find(f[t]))
    			{
    				f[t]=x;
    				f[x]=t;
    				return 1;
    			}
    		}
    		return 0;
    	}
    	inline void dfs(int x)
    	{
    		if(ans[x]) return;
    		ans[x]=1;
    		for(int i=head[x];i;i=a[i].nxt)
    		{
    			int t=a[i].to;
    			dfs(f[t]);
    		}
    	}
    	inline void main()
    	{
    		n=read(),m=read();
    		for(int i=1;i<=n;++i)
    		{
    			scanf("%s",s[i]+1);
    			for(int j=1;j<=m;++j)
    			{
    				if(s[i][j]=='.')
    				{
    					id[i][j]=++idx;
    					g[id[i][j]]=(i+j)&1;
    				}
    			}
    		}
    		for(int i=1;i<=n;++i)
    		{
    			for(int j=1;j<=m;++j)
    			{
    				if(!id[i][j]) continue;
    				for(int k=0;k<4;++k)
    				{
    					int tx=i+dx[k],ty=j+dy[k];
    					if(id[tx][ty]) link(id[i][j],id[tx][ty]);
    				}
    			}
    		}
    		for(int i=1;i<=idx;++i) if(g[i])
    		{
    			memset(vis,0,sizeof(vis));
    			tot+=find(i);
    		}
    		if(tot*2==n*m)
    		{
    			puts("LOSE");
    			return;
    		}
    		puts("WIN");
    		for(int i=1;i<=idx;++i)
    		{
    			if(!f[i]) dfs(i);
    		}
    		for(int i=1;i<=n;++i)
    		{
    			for(int j=1;j<=m;++j)
    			{
    				if(ans[id[i][j]]) printf("%lld %lld
    ",i,j);
    			}
    		}
    	}
    }
    signed main()
    {
    	red::main();
    return 0;
    }
    
  • 相关阅读:
    深入Android 【一】 —— 序及开篇
    Android中ContentProvider和ContentResolver使用入门
    深入Android 【六】 —— 界面构造
    The service cannot be activated because it does not support ASP.NET compatibility. ASP.NET compatibility is enabled for this application. Turn off ASP.NET compatibility mode in the web.config or add the AspNetCompatibilityRequirements attribute to the ser
    Dynamic Business代码片段总结
    对文件的BuildAction以content,resource两种方式的读取
    paraview 3.12.0 windows下编译成功 小记
    百度网盘PanDownload使用Aria2满速下载
    netdata的安装与使用
    用PS给证件照排版教程
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12084560.html
Copyright © 2011-2022 走看看