• loj6033.「雅礼集训 2017 Day2」棋盘游戏


    题意

    见到棋盘首先想黑白染色,之后对这个二分图跑一个最大匹配。

    假如一个棋子放在了一个非匹配点上,那么先手必败,因为后手每次都有匹配边可以走。

    于是我们要求有多少个点可能不在一个最大匹配中:
    考虑一个非匹配点(x),假如它连向了一个匹配点(y),那么它就能替换掉当前当前和这个匹配点匹配的点(z),而这时(z)也可以进行同样的操作。

    于是我们从每个非匹配(x)出发进行(dfs),途经的和(x)同一集合的点都满足要求。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=150;
    int n,m,cnt_edge,tim,ans;
    int head[maxn*maxn],match[maxn*maxn],vis[maxn*maxn];
    char a[maxn][maxn];
    bool check[maxn*maxn];
    inline int read()
    {
    	char c=getchar();int res=0,f=1;
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    	return res*f;
    }
    struct edge{int to,nxt;}e[maxn*maxn*8]; 
    inline void add_edge(int u,int v)
    {
        e[++cnt_edge].nxt=head[u];
        head[u]=cnt_edge;
        e[cnt_edge].to=v;
    }
    inline int id(int i,int j){return (i-1)*m+j;}
    bool dfs(int x)
    {
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(vis[y]==tim)continue;
    		vis[y]=tim;
    		if(!match[y]||dfs(match[y])){match[y]=x;match[x]=y;return 1;}
    	}
    	return 0;
    }
    void dfs_ans(int x)
    {
    	check[x]=1;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(!check[match[y]])dfs_ans(match[y]);
    	}
    }
    int main()
    {
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)scanf("%s",a[i]+1);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    		{
    			if(a[i][j]=='#')continue;
    			if(i<n&&a[i+1][j]=='.')add_edge(id(i,j),id(i+1,j)),add_edge(id(i+1,j),id(i,j));
    			if(j<m&&a[i][j+1]=='.')add_edge(id(i,j),id(i,j+1)),add_edge(id(i,j+1),id(i,j));
    		}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			if(((i+j)&1)&&a[i][j]=='.')
    				tim++,dfs(id(i,j));
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			if(a[i][j]=='.'&&!match[id(i,j)]&&!check[id(i,j)])
    				dfs_ans(id(i,j));
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			if(check[id(i,j)])ans++;
    	printf("%d
    ",ans);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			if(check[id(i,j)])printf("%d %d
    ",i,j);
    	return 0;
    }
    
  • 相关阅读:
    ar游戏开发入门三步走
    什么是 OpenCL OpenGL
    https 服务器搭建
    javascript 访问cookie信息
    手机网页制作需要注意的一点东西
    asp.net下载文件几种方式
    javascriptM
    PDF转JPG
    java实现PDF转HTML
    关于mysql ERROR 1045 (28000)错误的解决办法
  • 原文地址:https://www.cnblogs.com/nofind/p/12149757.html
Copyright © 2020-2023  润新知