zoukankan      html  css  js  c++  java
  • 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
    ",ans);
        return 0;
    }
  • 相关阅读:
    MongoDB简单使用
    mongodb安装部署
    分布式通信-序列化
    分布式通信协议
    分布式概念
    springboot-事件
    spring-事件
    spring-@Component/@ComponentScan注解
    springboot-Date日期时间问题
    enginx:基于openresty,一个前后端统一,生态共享的webstack实现
  • 原文地址:https://www.cnblogs.com/Narh/p/10162194.html
Copyright © 2011-2022 走看看