题意
给出n*m矩阵,给出k个漏洞所在坐标,问能不能用1*2的模板覆盖完全不是漏洞的点。
思路
按行+列奇偶性来分成两部分,因为1*2的矩形覆盖的和值一定奇偶性不同,和值为奇数的向上下左右(和值一定是偶数)连边,注意预处理出来每个点的标号。
#include <algorithm> //STL通用算法
#include <bitset> //STL位集容器
#include <cmath>
#include <cstdio>
#include <cstring>
#include <deque> //STL双端队列容器
#include <exception> //异常处理类
#include <fstream>
#include <functional> //STL定义运算函数(代替运算符)
#include <limits>
#include <list> //STL线性列表容器
#include <map> //STL 映射容器
#include <iomanip>
#include <ios> //基本输入/输出支持
#include<iosfwd> //输入/输出系统使用的前置声明
#include <iostream>
#include <istream> //基本输入流
#include <ostream> //基本输出流
#include <queue> //STL队列容器
#include <set> //STL 集合容器
#include <sstream> //基于字符串的流
#include <stack> //STL堆栈容器
#include <string> //字符串类
#include <vector> //STL动态数组容器
#define ll long long
using namespace std;
#define ll long long
#define maxn 1000+66
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define mod 1000000007
#define INF 0x3f3f3f3f
struct node
{
int to;
int nxt;
} e[maxn*maxn];
struct Two///0开头
{
int head[maxn*2];
int color[maxn];
int dep[maxn];
int dx[maxn];
int dy[maxn];
int mx[maxn];
int my[maxn];
int n,m,cnt;
void init(int nn,int mm)
{
cnt=0;
n=nn;
m=mm;
///cout<<n<<" "<<m<<endl;
rep(i,0,maxn*2-1)head[i]=-1;
}
void add_edge(int u,int v)
{
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
}
int bfs()
{
int flag=0;
queue<int>q;
for(int i=0; i<=n+1; i++)
{
dx[i]=-1;
}
for(int i=0; i<=m+1; i++)
{
dy[i]=-1;
}
for(int i=0; i<n; i++)
if(mx[i]==-1)
q.push(i);
while(!q.empty())
{
int u=q.front();
//cout<<u<<endl;
q.pop();
for(int k=head[u]; k!=-1; k=e[k].nxt)
{
int v=e[k].to;
if(dy[v]==-1)
{
dy[v]=dx[u]+1;
if(my[v]==-1)
flag=1;
else
{
dx[my[v]]=dy[v]+1;
q.push(my[v]);
}
}
}
}
return flag;
}
bool dfs(int u)
{
//cout<<u<<endl;
for(int k=head[u]; k!=-1; k=e[k].nxt)
{
int v=e[k].to;
if(dy[v]==dx[u]+1)
{
dy[v]=-1;
if(my[v]==-1||dfs(my[v]))
{
my[v]=u;
mx[u]=v;
return 1;
}
}
}
return 0;
}
int solve()
{
for(int i=0; i<=n+1; i++)
{
mx[i]=-1;
}
for(int i=0; i<=m+1; i++)
{
my[i]=-1;
}
int ans = 0;
while(bfs())
{
//cout<<"11"<<endl;
for(int i = 0; i < n; ++i)
if(mx[i] == -1 && dfs(i))
ans++;
}
return ans;
}
} D;
int vis[maxn][maxn];
int id[maxn][maxn];
int main()
{
int n,m,k;
while(scanf("%d %d %d",&n,&m,&k)!=EOF)
{
memset(vis,0,sizeof(vis));
memset(id,0,sizeof(id));
rep(i,1,k)
{
int x,y;
scanf("%d %d",&x,&y);
vis[y][x]=1;
}
int un=0,uv=0;
rep(i,1,n)
{
rep(j,1,m)
{
if(!vis[i][j]&&((i+j)%2==1))///
{
id[i][j]=un++;
}
else if(!vis[i][j]&&((i+j)%2==0))
{
id[i][j]=uv++;
}
}
}
D.init(un,uv);
rep(i,1,n)
{
rep(j,1,m)
{
if(!vis[i][j]&&(i+j)%2==1)
{
///un++;
if(j+1<=m&&!vis[i][j+1])
{
///uv++;
D.add_edge(id[i][j],id[i][j+1]);
}
if(j-1>0&&!vis[i][j-1])
{
///uv++;
D.add_edge(id[i][j],id[i][j-1]);
}
if(i-1>0&&!vis[i-1][j])
{
///uv++;
D.add_edge(id[i][j],id[i-1][j]);
}
if(i+1<=n&&!vis[i+1][j])
{
///uv++;
D.add_edge(id[i][j],id[i+1][j]);
}
}
}
}
int ans=D.solve();
ans=n*m-k-ans*2;
if(ans!=0)
{
printf("NO\n");
}
else
{
printf("YES\n");
}
}
}
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define maxn 1111
int uN,vN;//u,v数目
int g[maxn][maxn];//编号是0~n-1的
int linker[maxn];
bool used[maxn];
bool dfs(int u)
{
int v;
for(v=0;v<vN;v++)
if(g[u][v]&&!used[v])
{
used[v]=true;
if(linker[v]==-1||dfs(linker[v]))
{
linker[v]=u;
return true;
}
}
return false;
}
int hungary()
{
int res=0;
int u;
memset(linker,-1,sizeof(linker));
for(u=0;u<uN;u++)
{
memset(used,0,sizeof(used));
if(dfs(u)) res++;
}
return res;
}
int main()
{
int n,m,k,Map[33][33];
while(~scanf("%d%d%d",&n,&m,&k))
{
memset(g,0,sizeof(g));
uN=vN=0;
memset(Map,0,sizeof(Map));
for(int i=1;i<=k;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Map[y][x]=-1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(Map[i][j]==-1)continue;
if((i+j)%2)Map[i][j]=uN++;
else Map[i][j]=vN++;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(Map[i][j]!=-1&&((i+j)%2))
{
if(i-1>=1&&Map[i-1][j]!=-1)g[Map[i][j]][Map[i-1][j]]=1;
if(i+1<=n&&Map[i+1][j]!=-1)g[Map[i][j]][Map[i+1][j]]=1;
if(j-1>=1&&Map[i][j-1]!=-1)g[Map[i][j]][Map[i][j-1]]=1;
if(j+1<=m&&Map[i][j+1]!=-1)g[Map[i][j]][Map[i][j+1]]=1;
}
if(hungary()*2==m*n-k)printf("YES\n");
else printf("NO\n");
}
return 0;
}