BZOJ 4823 [Cqoi2017]老C的方块 ——网络流

lrd的题解:http://www.cnblogs.com/liu-runda/p/6695139.html

我还是太菜了。以后遇到这种题目应该分析分析性质的。

网络流复杂度真是$O(玄学)$

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define inf 0x3f3f3f3f
#define ll long long
#define mp make_pair
#define maxn 500005
 
int mov[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int h[maxn],to[maxn],ne[maxn],fl[maxn],en=0,n,m,k;
int S=maxn-2,T=maxn-1,dis[maxn];
queue <int> q;
map <pair<int,int>,int> Link;
 
void add(int a,int b,int c)
{
    to[en]=b;ne[en]=h[a];fl[en]=c;h[a]=en++;
    to[en]=a;ne[en]=h[b];fl[en]=0;h[b]=en++;
}
 
bool tell()
{
    memset(dis,-1,sizeof dis); dis[S]=0; q.push(S);
    while (!q.empty())
    {
        int x=q.front(); q.pop();
        for (int i=h[x];i>=0;i=ne[i])
        if (dis[to[i]]==-1&&fl[i]>0){
            dis[to[i]]=dis[x]+1;
            q.push(to[i]);
        }
    }
    return dis[T]!=-1;
}
 
int zeng(int k,int now)
{
    if (k==T) return now;
    int ret=0;
    for (int i=h[k];i>=0&&ret<now;i=ne[i])
        if (dis[to[i]]==dis[k]+1&&fl[i]>0)
        {
            int tmp=zeng(to[i],min(fl[i],now-ret));
            fl[i]-=tmp;fl[i^1]+=tmp;ret+=tmp;
        }
    if (!ret) dis[k]=-1;
    return ret;
}
 
int dinic()
{
    int ret=0,tmp;
    while (tell()) while (tmp=zeng(S,inf)) ret+=tmp;
    return ret;
}
 
int x[maxn],y[maxn],w[maxn];
 
bool isgreen(int x,int y)
{
    int tmp=(x>>1)&1;
    if (tmp) return ((x+y)&1);
    else return (!((x+y)&1));
}
 
bool isblue(int x,int y)
{if ((!isgreen(x,y))&&(!((x>>1)&1))) return true;return false;}
 
bool isred(int x,int y)
{if ((!isgreen(x,y))&&(!isblue(x,y))) return true;return false;}
 
bool leftgreen(int x,int y)
{return (isgreen(x,y))&&(isred(x,y+1))&&(isgreen(x+1,y));}
 
bool rightgreen(int x,int y)
{return (isgreen(x,y))&&(isred(x,y+1))&&(isgreen(x-1,y));}
 
void Finout()
{
    freopen("block.in","r",stdin);
    freopen("block.out","w",stdout);
}
 
int main()
{
    memset(h,-1,sizeof h);
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    F(i,1,k)
    {
        scanf("%d%d%d",&x[i],&y[i],&w[i]);
        if (isred(x[i],y[i])) add(S,i,w[i]);
        else if (isblue(x[i],y[i])) add(i,T,w[i]);
        Link[mp(x[i],y[i])]=i;
    }
    F(i,1,k)
    {
        if (isblue(x[i],y[i]))
        {
            F(k,0,3)
            {
                int tx=x[i]+mov[k][0],tmp,ty=y[i]+mov[k][1];
                if (tx>=1&&tx<=n&&ty>=1&&ty<=m&&isgreen(tx,ty)&&(tmp=Link[mp(tx,ty)]))
                    add(tmp,i,inf);
            }
        }
        else if (isred(x[i],y[i]))
        {
            F(k,0,3)
            {
                int tx=x[i]+mov[k][0],tmp,ty=y[i]+mov[k][1];
                if (tx>=1&&tx<=n&&ty>=1&&ty<=m&&isgreen(tx,ty)&&(tmp=Link[mp(tx,ty)]))
                    add(i,tmp,inf);
            }
        }
        else if (leftgreen(x[i],y[i]))
        {
            int tmp;
            if ((tmp=Link[mp(x[i]+1,y[i])]))
                add(i,Link[mp(x[i]+1,y[i])],min(w[i],w[tmp]));
        }
        else if (rightgreen(x[i],y[i]))
        {
            int tmp;
            if ((tmp=Link[mp(x[i]-1,y[i])]))
                add(i,Link[mp(x[i]-1,y[i])],min(w[i],w[tmp]));
        }
    }
    printf("%d\n",dinic());
}

  

posted @ 2017-04-20 09:00  SfailSth  阅读(128)  评论(0编辑  收藏  举报