【CQOI2017】bzoj4823 老C的方块

177 篇文章 1 订阅
115 篇文章 0 订阅

可以注意到,每一个讨厌的形状,都可以看成一条特殊边两侧的方块再各连出去一个方块。
这样我们可以把格子分成四类,如图。
这里写图片描述
每一个讨厌的形状,都可以看成是黄→黑→红→绿。因此分四层建图跑最小割就行了。

#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
const int maxn=100010,s=100005,t=100006,oo=0x3f3f3f3f;
int rd()
{
    int x=0;
    char c=getchar();
    while (c<'0'||c>'9') c=getchar();
    while (c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    return x;
}
int fir[maxn],cur[maxn],ne[20*maxn],to[20*maxn],w[20*maxn],dep[maxn],que[maxn],
xx[maxn],yy[maxn],ww[maxn],
n,num,r,c;
map<pair<int,int>,int> id;
void check()
{
    for (int i=1;i<=t;i++)
        for (int j=fir[i];j;j=ne[j])
            if (w[j])
                printf("%d->%d:%d\n",i,to[j],w[j]);
}
void add(int u,int v,int x)
{
    num++;
    ne[num*2]=fir[u];
    fir[u]=num*2;
    to[num*2]=v;
    w[num*2]=x;
    ne[num*2+1]=fir[v];
    fir[v]=num*2+1;
    to[num*2+1]=u;
    w[num*2+1]=0;
}
bool bfs()
{
    int u,v,hd,tl;
    for (int i=1;i<=n;i++) dep[i]=0;
    dep[t]=0;
    dep[s]=1;
    que[hd=tl=1]=s;
    while (hd<=tl)
    {
        u=que[hd++];
        for (int i=fir[u];i;i=ne[i])
            if (w[i]&&!dep[v=to[i]])
            {
                dep[v]=dep[u]+1;
                que[++tl]=v;
            }
    }
    return dep[t];
}
int dfs(int u,int lim)
{
    if (u==t) return lim;
    int v,x,ret=0;
    for (int &i=cur[u];i&&ret<lim;i=ne[i])
        if (w[i]&&dep[v=to[i]]==dep[u]+1)
        {
            x=dfs(v,min(lim-ret,w[i]));
            ret+=x;
            w[i]-=x;
            w[i^1]+=x;
        }
    return ret;
}
int main()
{
    /*freopen("block.in","r",stdin);
    freopen("block.out","w",stdout);*/
    int u,ans=0;
    c=rd();
    r=rd();
    n=rd();
    for (int i=1;i<=n;i++)
    {
        xx[i]=rd();
        yy[i]=rd();
        ww[i]=rd();
        id[make_pair(xx[i],yy[i])]=i;
    }
    for (int i=1;i<=n;i++)
        switch (xx[i]%4)
        {
            case 0:
                if (yy[i]&1) add(s,i,ww[i]);
                else
                {
                    if (id.count(make_pair(xx[i]+1,yy[i])))
                        add(id[make_pair(xx[i]+1,yy[i])],i,oo);
                    if (id.count(make_pair(xx[i],yy[i]+1)))
                        add(id[make_pair(xx[i],yy[i]+1)],i,oo);
                    if (id.count(make_pair(xx[i],yy[i]-1)))
                        add(id[make_pair(xx[i],yy[i]-1)],i,oo);
                }
                break;
            case 1:
                if (yy[i]&1)
                {
                    if (id.count(make_pair(xx[i]-1,yy[i])))
                        add(id[make_pair(xx[i]-1,yy[i])],i,oo);
                    if (id.count(make_pair(xx[i],yy[i]+1)))
                        add(id[make_pair(xx[i],yy[i]+1)],i,oo);
                    if (id.count(make_pair(xx[i],yy[i]-1)))
                        add(id[make_pair(xx[i],yy[i]-1)],i,oo);
                    if (id.count(make_pair(xx[i]+1,yy[i])))
                    {
                        u=id[make_pair(xx[i]+1,yy[i])];
                        add(i,u,min(ww[i],ww[u]));
                    }
                }
                else add(s,i,ww[i]);
                break;
            case 2:
                if (yy[i]&1)
                {
                    if (id.count(make_pair(xx[i]+1,yy[i])))
                        add(i,id[make_pair(xx[i]+1,yy[i])],oo);
                    if (id.count(make_pair(xx[i],yy[i]+1)))
                        add(i,id[make_pair(xx[i],yy[i]+1)],oo);
                    if (id.count(make_pair(xx[i],yy[i]-1)))
                        add(i,id[make_pair(xx[i],yy[i]-1)],oo);
                }
                else add(i,t,ww[i]);
                break;
            case 3:
                if (yy[i]&1) add(i,t,ww[i]);
                else
                {
                    if (id.count(make_pair(xx[i]-1,yy[i])))
                        add(i,id[make_pair(xx[i]-1,yy[i])],oo);
                    if (id.count(make_pair(xx[i],yy[i]+1)))
                        add(i,id[make_pair(xx[i],yy[i]+1)],oo);
                    if (id.count(make_pair(xx[i],yy[i]-1)))
                        add(i,id[make_pair(xx[i],yy[i]-1)],oo);
                    if (id.count(make_pair(xx[i]+1,yy[i])))
                    {
                        u=id[make_pair(xx[i]+1,yy[i])];
                        add(u,i,min(ww[i],ww[u]));
                    }
                }
        }
    //check();
    while (bfs())
    {
        for (int i=1;i<=n;i++) cur[i]=fir[i];
        cur[s]=fir[s];
        cur[t]=fir[t];
        ans+=dfs(s,oo);
    }
    printf("%d\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值