网络流习题

E. Rectangle Painting 2

网络流习题_第1张图片
链接:https://codeforces.ml/contest/1198/problem/E

题意:给定一个 n × n n\times n n×n 的网格图,给出 m 个矩阵将格子染成黑色。你可以选择任意大小的矩阵 h × w h\times w h×w,并花费 m i n ( h , w ) min(h,w) min(h,w) 将选择的矩阵染回白色。你可以操作任意多次,问将网格图全部染回白色的最小代价

思路

  • 把行、列看成一个点,每一行与源点的流量为 1,每一列与源点的流量也为 1 。行和列之间的流量可以任意大于等于 1 即可。
  • n 很大,所以可以离散化后维护块,把一块看成一个点,流量为这个块的行数(或者列数)
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;

namespace Dinic
{
    const int MAXN=310,MAXM=2e6+10,inf=1e9+10;
    int head[MAXN],cur[MAXN],cnt;
    int depth[MAXN];
    int maxvex;

    struct Edge
    {
        int nxt,to,flow;
    } edges[MAXM<<1];
    void init(int n)
    {
        maxvex=n,cnt=-1;
        for(int i=0; i<=n; ++i) head[i]=-1;
    }
    void add(int u,int v,int flow)
    {
        edges[++cnt]= {head[u],v,flow};
        head[u]=cnt;
        edges[++cnt]= {head[v],u,0};
        head[v]=cnt;
    }
    bool bfs(int s,int t)
    {
        for(int i=0; i<=maxvex; ++i)
            cur[i]=head[i],depth[i]=inf;
        queue<int> q;
        q.push(s);
        depth[s]=0;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u]; i!=-1; i=edges[i].nxt)
            {
                int v=edges[i].to,flow=edges[i].flow;
                if(depth[v]==inf&&flow)
                {
                    depth[v]=depth[u]+1;
                    q.push(v);
                }
            }
        }
        return depth[t]<inf;
    }
    int dfs(int u,int t,int curflow)//当前边的流
    {
        if(curflow==0||u==t) return curflow;
        int flow=0,f;
        for(int i=cur[u]; i!=-1; i=edges[i].nxt)
        {
            cur[u]=i;//当前弧优化
            int v=edges[i].to,eflow=edges[i].flow;
            if(depth[v]==depth[u]+1&&(f=dfs(v,t,min(curflow,eflow))))
            {
                flow+=f;
                curflow-=f;
                edges[i].flow-=f;
                edges[i^1].flow+=f;
                if(curflow==0) break;
            }
        }
        return flow;
    }
    int maxflow(int s,int t)
    {
        int cnt=0;
        int flow=0,f;
        while(bfs(s,t))
            while((f=dfs(s,t,inf))>0)
                flow+=f;
        return flow;
    }
};

int n,m;
vector<int> allx,ally;
struct Opt
{
    int x1,x2,y1,y2;
} opt[60];

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; ++i)
    {
        int x1,x2,y1,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        x1--,y1--;
        opt[i]= {x1,x2,y1,y2};
        allx.push_back(x1),allx.push_back(x2);
        ally.push_back(y1),ally.push_back(y2);
    }
    sort(allx.begin(),allx.end());
    sort(ally.begin(),ally.end());
    allx.resize(unique(allx.begin(),allx.end())-allx.begin());
    ally.resize(unique(ally.begin(),ally.end())-ally.begin());

    Dinic::init(300);
    int s=200,t=201;
    for(int i=1; i<allx.size(); ++i)
        Dinic::add(s,i,allx[i]-allx[i-1]);
    for(int i=1; i<ally.size(); ++i)
        Dinic::add(i+100,t,ally[i]-ally[i-1]);

    for(int i=1; i<=m; ++i)
    {
        int x1=lower_bound(allx.begin(),allx.end(),opt[i].x1)-allx.begin()+1;
        int x2=lower_bound(allx.begin(),allx.end(),opt[i].x2)-allx.begin()+1;
        int y1=lower_bound(ally.begin(),ally.end(),opt[i].y1)-ally.begin()+1;
        int y2=lower_bound(ally.begin(),ally.end(),opt[i].y2)-ally.begin()+1;
        for(int j=x1; j<x2; ++j)
            for(int k=y1; k<y2; ++k)
                Dinic::add(j,k+100,1e9+10);
    }
    int ans=Dinic::maxflow(s,t);
    printf("%d\n",ans);
    return 0;
}

你可能感兴趣的:(图论,图论,-,网络流)