Codeforces Round #576 (Div. 1)

E. Rectangle Painting 2

题意:
给你一个n *n的矩阵,里面有一些棋盘被染成黑色了,现在让你求把所有黑色的矩阵全部染成白色的最小费用是多少?最小费用的计算方式是:min(h,w)。

输入:
输入一个n,和一个m(代表黑色矩阵的个数),然后在输入每一个矩阵的左下角和右上角的坐标。

输出:
最小费用

分析:
由于数据规模庞大,要使费用最小,就是一整行或者一整列包含的黑色格子多一点,这样我们费用就会少一点,那么我们将行和列拆开来看,把黑色格子的行视为一部分,列视为一部分,那么我们要用最少行或列来将整个黑色矩形覆盖,那么就最小点覆盖,用最小的点覆盖所有边,即二分图,我们有一个性质:最大流=最小割=最小点覆盖=最大匹配,所以这里我们可以用Dinic算法来求解这题,复杂度为O(m*n^2),这里的n不是矩阵的大小,而时每个黑色矩阵的坐标,我们首先将所有黑色矩阵矩形离散化一下,设一个超级源点S,从S到所有的黑色矩阵的x坐标建一条流量为X[i+1]-X[i]的边(X[i+1]-X[i]表示这个两个x坐标中间有多少黑色格子),我们在设一个超级汇点T,从T到所有的黑色矩阵的y坐标建一条流量为Y[i+1]-Y[i]的边,然后我们在求一下建x到y的边,这个边怎么建呢?首先我们求出每一个矩阵所对应离散化后的坐标,得到一块连续的区间(矩阵),然后这块矩阵的每一个x到y这边建一条无穷大的边,最后在跑一遍Dinic算法就搞定了。
如果以上不明白自己画一个图就搞定了。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int MAXN=250+5;
const int MAXM=6e5+5;
const int INF=0x3f3f3f3f;
struct point
{
    int x1,y1,x2,y2;
}arr[MAXN];
int X[MAXN<<1],Y[MAXN<<1];
struct node
{
    int to,cap,next;
}edges[MAXM];
int head[MAXN<<1],edge;
int iter[MAXN<<1];//当前弧优化
int level[MAXN<<1];//分层
int vis[MAXN<<1][MAXN<<1];
void init()
{
    memset(vis,0,sizeof(vis));
    memset(head,-1,sizeof(head));
    edge=0;
}
void addedges(int u,int v,int cap)
{
    edges[edge].to=v;
    edges[edge].cap=cap;
    edges[edge].next=head[u];
    head[u]=edge++;

    edges[edge].to=u;
    edges[edge].cap=0;
    edges[edge].next=head[v];
    head[v]=edge++;
}
bool bfs(int s,int t)
{
    memset(level,-1,sizeof(level));
    level[s]=1;
    queue<int>que;
    que.push(s);
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        for(int i=head[u];i!=-1;i=edges[i].next)
        {
            int v=edges[i].to;
            int cap=edges[i].cap;
            if(cap>0&&level[v]<0)
            {
                level[v]=level[u]+1;
                if(v==t)return true;
                que.push(v);
            }
        }
    }
    return level[t]!=-1;
}
int dfs(int s,int t,int f)
{
    if(s==t)return f;
    for(int &i=iter[s];i!=-1;i=edges[i].next)
    {
        int v=edges[i].to;
        int cap=edges[i].cap;
        if(cap>0&&level[v]==level[s]+1)
        {
            int d=dfs(v,t,min(f,cap));
            if(d>0)
            {
                edges[i].cap-=d;
                edges[i^1].cap+=d;
                return d;
            }
        }
    }
    return 0;
}
int Dinic(int s,int t)
{
    int ans=0;
    while(bfs(s,t))
    {
        memcpy(iter,head,sizeof(iter));
        while(int d=dfs(s,t,INF))ans+=d;
    }
    return ans;
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int num=0;
        init();
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d%d",&arr[i].x1,&arr[i].y1,&arr[i].x2,&arr[i].y2);
            X[num]=--arr[i].x1;
            Y[num++]=--arr[i].y1;
            X[num]=arr[i].x2;
            Y[num++]=arr[i].y2;
        }
        X[num]=Y[num++]=0;
        X[num]=Y[num++]=n;
        sort(X,X+num);
        int tot_x=unique(X,X+num)-X;
        sort(Y,Y+num);
        int tot_y=unique(Y,Y+num)-Y;
        int s=210,t=215;
        for(int i=0;i<tot_x-1;i++)
        {
            addedges(s,i+1,X[i+1]-X[i]);
        }
        for(int i=0;i<tot_y-1;i++)
        {
            addedges(i+tot_x,t,Y[i+1]-Y[i]);
        }
        for(int i=1;i<=m;i++)
        {
            int x1=lower_bound(X,X+tot_x,arr[i].x1)-X;
            int y1=lower_bound(Y,Y+tot_y,arr[i].y1)-Y;
            int x2=lower_bound(X,X+tot_x,arr[i].x2)-X;
            int y2=lower_bound(Y,Y+tot_y,arr[i].y2)-Y;
            for(int j=x1;j<x2;j++)
            {
                for(int k=y1;k<y2;k++)
                {
                    vis[j+1][k+1]=1;
                }
            }
        }
        for(int i=0;i<tot_x-1;i++)
        {
            for(int j=0;j<tot_y-1;j++)
            {
                if(vis[i+1][j+1])
                {
                    addedges(i+1,j+tot_x,INF);
                }
            }
        }
        printf("%d\n",Dinic(s,t));
    }
    return 0;
}
Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Puzzle harvester

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值