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

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4823

一个不合法方案其实就是蓝线的两边格子一定选、剩下两部分四相邻格子里各选一个。

所以这个图是一个四分图。记蓝线左边格子是1,右边是2,与 1 四相邻的是3,与 2 四相邻的是4;这个部分右边就是蓝线左边是2、右边是1,这样。

有一些“4个格子不能同时选”的限制,考虑怎么在图中表示。

需要做到的是4个格子里割掉一个就能让这条路径废掉,那么应该是把有联系的4个点连成一条链。因为是4分图,所以能做到。

一个格子可能在很多路径里,如果在路径的边上放权值,不能表示割掉这个格子可以使很多路径都废掉。所以把格子拆成两个点,自己向自己连的边上放权值即可。

 map 是一个有序结构,所以结构体的话要定义小于号。如果只定义了 x<b.x ,那么在 x==b.x 的时候 map 会认为这是同一个点!即使它们的 y 不同。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int N=2e5+5,M=2e6+5,INF=1e9+5;
int n,r,c,t,x[N],y[N],w[N];
int hd[N],xnt=1,cur[N],to[M],nxt[M],cap[M];
int dfn[N],q[N],he,tl;
struct Node{
    int x,y;
    Node(int a=0,int b=0):x(a),y(b) {}
    bool operator< (const Node &b)const
    {return x==b.x?y<b.y:x<b.x;}//////x<b.x will rec x==b.x as the same point
};
map<Node,int> mp;
int Mn(int a,int b){return a<b?a:b;}
int rdn()
{
    int ret=0;bool fx=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
    while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
    return fx?ret:-ret;
}
void add(int x,int y,int z)
{
    to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;cap[xnt]=z;
    to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt;cap[xnt]=0;
}
bool bfs()
{
    memset(dfn,0,sizeof dfn);dfn[0]=1;
    q[he=tl=1]=0;
    while(he<=tl)
    {
        int k=q[he++];
        for(int i=hd[k],v;i;i=nxt[i])
            if(cap[i]&&!dfn[v=to[i]])
                dfn[v]=dfn[k]+1,q[++tl]=v;
    }
    return dfn[t];
}
int dinic(int cr,int flow)
{
    if(cr==t)return flow;
    int use=0;
    for(int& i=cur[cr],v;i;i=nxt[i])
        if(cap[i]&&dfn[v=to[i]]==dfn[cr]+1)
        {
            int tmp=dinic(v,Mn(flow-use,cap[i]));
            if(!tmp)dfn[v]=0;
            use+=tmp;cap[i]-=tmp;cap[i^1]+=tmp;
            if(use==flow)return use;
        }
    return use;
}
int main()
{
    c=rdn();r=rdn();n=rdn();
    for(int i=1;i<=n;i++)
    {
        y[i]=rdn();x[i]=rdn();w[i]=rdn();//y[] then x[]
        mp[Node(x[i],y[i])]=i;
    }
    t=(n<<1)+1; Node o;
    for(int i=1;i<=n;i++)
    {
        add(i,i+n,w[i]);
        int u=(x[i]&1),v=(y[i]&3);
        if((u&&!v)||(!u&&v==1))add(0,i,INF);//3
        else if((u&&v==3)||(!u&&v==2))add(i+n,t,INF);//4
        else if((u&&v==1)||(!u&&!v))//1
        {
            if(mp.count(o=Node(x[i]-1,y[i])))//3->1
                add(mp[o]+n,i,INF);
            if(mp.count(o=Node(x[i]+1,y[i])))
                add(mp[o]+n,i,INF);
            if(mp.count(o=Node(x[i],y[i]+1)))//1>2 or 3>1
                u?add(i+n,mp[o],INF):add(mp[o]+n,i,INF);
            if(mp.count(o=Node(x[i],y[i]-1)))
                u?add(mp[o]+n,i,INF):add(i+n,mp[o],INF);
        }
        else//2
        {
            if(mp.count(o=Node(x[i]-1,y[i])))
                add(i+n,mp[o],INF);
            if(mp.count(o=Node(x[i]+1,y[i])))
                add(i+n,mp[o],INF);
            if(mp.count(o=Node(x[i],u?y[i]+1:y[i]-1)))
                add(i+n,mp[o],INF);
        }
    }
    int ans=0;
    while(bfs())memcpy(cur,hd,sizeof hd),ans+=dinic(0,INF);
    printf("%d\n",ans);
    return 0;
}

 

posted on 2018-12-22 19:30  Narh  阅读(139)  评论(0编辑  收藏  举报

导航