2012 TCO Algorithm Round 3A - Division I, Level Two FoxAndCake

竟然是网络流问题!

因为每个联通块要含有两种东西,且每个格子都只能出现在一个联通块上,所以我们可以吧一个联通块看成从一种东西到另一种东西的路径。为了实现第二个条件,我们在每个点上限制流量就可以了。那么现在的问题就是图太大了。但是只有7个点,我们可以把有用的X,Y坐标离散化出来。官方题解证明了对与每一个X,只要提取出[X-3,X+3]这7个数字就可以了。这样我们建图跑最大流就可以了。

#include <bits/stdc++.h>
#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]<n)res+=dfs(src,INF);
    return res;
}
vector<int>X,Y;
map<pair<int,int>,int>mp;
int dx[]={0,0,-1,1};
int dy[]={-1,1,0,0};
void build(int n,vector<int>&x,vector<int>&ans)
{
	set<int>st;
	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<int>::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 <int> x, vector <int> 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";
}
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值