竟然是网络流问题!
因为每个联通块要含有两种东西,且每个格子都只能出现在一个联通块上,所以我们可以吧一个联通块看成从一种东西到另一种东西的路径。为了实现第二个条件,我们在每个点上限制流量就可以了。那么现在的问题就是图太大了。但是只有7个点,我们可以把有用的X,Y坐标离散化出来。官方题解证明了对与每一个X,只要提取出[X-3,X+3]这7个数字就可以了。这样我们建图跑最大流就可以了。
#include
#define maxn 6000
#define maxm 2000009
using namespace std;
const int INF=1e9;
struct Edge
{
int v,next,cap;
}edge[maxm];
int head[maxn],h[maxn],gap[maxn],tot,n,src,des,N;
inline void addedge(int u,int v,int cap)
{
// printf(">>%d %d\n",u,v);
edge[tot].v=v;
edge[tot].cap=cap;
edge[tot].next=head[u];
head[u]=tot++;
edge[tot].v=u;
edge[tot].cap=0;
edge[tot].next=head[v];
head[v]=tot++;
}
inline int dfs(int u,int cap)
{
if(u==des)return cap;
int minh=n-1;
int lv=cap,d;
for(int e=head[u];e!=-1;e=edge[e].next)
{
int v=edge[e].v;
int w=edge[e].cap;
if(w>0)
{
if(h[v]+1==h[u])
{
d=min(lv,edge[e].cap);
d=dfs(v,d);
edge[e].cap-=d;
edge[e^1].cap+=d;
lv-=d;
if(h[src]>=n)return cap-lv;
if(lv==0)
break;
}
minh=min(minh,h[v]);
}
}
if(lv==cap)
{
--gap[h[u]];
if(gap[h[u]]==0)h[src]=n;
h[u]=minh+1;
++gap[h[u]];
}
return cap-lv;
}
int sap()
{
int res=0;
memset(gap,0,sizeof(gap));
memset(h,0,sizeof(h));
gap[0]=n;
while(h[src]X,Y;
map,int>mp;
int dx[]={0,0,-1,1};
int dy[]={-1,1,0,0};
void build(int n,vector&x,vector&ans)
{
setst;
for(int i=0;i<(int)x.size();i++)
{
for(int j=max(1,x[i]-3);j<=min(n,x[i]+3);j++)
st.insert(j);
}
for(set::iterator it=st.begin();it!=st.end();++it)
ans.push_back(*it);
sort(ans.begin(),ans.end());
return;
}
class FoxAndCake
{
public: string ableToDivide(int N, int M, vector x, vector y)
{
build(N,x,X);build(M,y,Y);
n=(int)X.size()*Y.size();
src=0;des=2*n+1;
int num=0;
memset(head,-1,sizeof(head));tot=0;
for(int i=0;i<(int)X.size();i++)
for(int j=0;j<(int)Y.size();j++)
{
mp[make_pair(X[i],Y[j])]=++num;
// printf("id %d %d is %d\n",X[i],Y[j],num);
}
printf("%d\n",num);
for(int i=1;i<=n;i++)
{
if(mp[make_pair(x[0],y[0])]==i)
continue;
else
addedge(i,i+n,1);
}
for(int i=1;i<4;i++)
{
addedge(src,mp[make_pair(x[i],y[i])],1);
}
for(int i=4;i<7;i++)
{
addedge(mp[make_pair(x[i],y[i])]+n,des,1);
}
for(int i=0;i<(int)X.size();i++)
for(int j=0;j<(int)Y.size();j++)
{
for(int k=0;k<4;k++)
{
int ni=i+dx[k];
int nj=j+dy[k];
if(ni<0||ni>=(int)X.size())
continue;
if(nj<0||nj>=(int)Y.size())
continue;
addedge(mp[make_pair(X[i],Y[j])]+n,mp[make_pair(X[ni],Y[nj])],INF);
}
}
n=des+1;
int flow=sap();
if(flow>=3)
return "Yes";
else
return "No";
}
};