zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    git让线上代码强制覆盖本地的
    redis连接时报错:Could not connect to Redis at 127.0.0.1:6379: Connection refused
    Apache使用内置插件mod_php解析php的配置
    Apache2.4+PHP7.2配置站点访问变下载
    Linux下查看某一进程所占用内存的方法
    SNMP监控一些常用OID的总结
    kafka 生产消费原理详解
    HttpServletRequest接收参数的几种方法
    【转载】idea 2018注册码(激活码)永久性的
    SecureCRT & SecureFx 绿色破解版
  • 原文地址:https://www.cnblogs.com/nofind/p/12149757.html
Copyright © 2011-2022 走看看