zoukankan      html  css  js  c++  java
  • CF1198E Rectangle Painting 2

    VI.CF1198E Rectangle Painting 2

    这题要点是想到一个贪心:染色的时候一定是一次把一行或一列全染完,费用为\(1\)。有了这个结论,就可以进行匹配了。

    首先,我们将矩形改写成左闭右开的形式,并进行离散化。然后,同上一题一样,只不过这道题是单次匹配的费用可能不为\(1\)(因为进行了离散化),因此跑的是带权最大匹配。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<algorithm>
    using namespace std;
    int n,m;
    struct node{
    	int x1,x2,y1,y2;
    }rec[110];
    vector<int>u,v;
    bool occ[210][210];
    namespace MaxFlow{
    	const int N=1000,M=2000000;
    	int head[N],cur[N],dep[N],cnt,S,T,res;
    	struct node{
    		int to,next,val;
    	}edge[M];
    	void ae(int u,int v,int w){
    		edge[cnt].next=head[u],edge[cnt].to=v,edge[cnt].val=w,head[u]=cnt++;
    		edge[cnt].next=head[v],edge[cnt].to=u,edge[cnt].val=0,head[v]=cnt++;
    	}
    	queue<int>q;
    	inline bool bfs(){
    		memset(dep,0,sizeof(dep)),q.push(S),dep[S]=1;
    		while(!q.empty()){
    			register int x=q.front();q.pop();
    			for(register int i=cur[x]=head[x];i!=-1;i=edge[i].next)if(edge[i].val&&!dep[edge[i].to])dep[edge[i].to]=dep[x]+1,q.push(edge[i].to);
    		}
    		return dep[T]>0;
    	}
    	bool reach;
    	inline int dfs(int x,int flow){
    		if(x==T){
    			res+=flow;
    			reach=true;
    			return flow;
    		}
    		int used=0;
    		for(register int &i=cur[x];i!=-1;i=edge[i].next){
    			if(!edge[i].val||dep[edge[i].to]!=dep[x]+1)continue;
    			register int ff=dfs(edge[i].to,min(edge[i].val,flow-used));
    			if(ff){
    				edge[i].val-=ff;
    				edge[i^1].val+=ff;
    				used+=ff;
    				if(used==flow)break;
    			}
    		}
    		return used;
    	}
    	inline void Dinic(){
    		while(bfs()){
    			reach=true;
    			while(reach)reach=false,dfs(S,0x3f3f3f3f);
    		}
    	}
    }
    using namespace MaxFlow;
    int main(){
    	scanf("%d%d",&n,&m),memset(head,-1,sizeof(head));
    	for(int i=1;i<=m;i++)scanf("%d%d%d%d",&rec[i].x1,&rec[i].y1,&rec[i].x2,&rec[i].y2),rec[i].x2++,rec[i].y2++,u.push_back(rec[i].x1),u.push_back(rec[i].x2),v.push_back(rec[i].y1),v.push_back(rec[i].y2);
    	sort(u.begin(),u.end()),u.resize(unique(u.begin(),u.end())-u.begin());
    	sort(v.begin(),v.end()),v.resize(unique(v.begin(),v.end())-v.begin());
    	S=u.size()+v.size()+1,T=u.size()+v.size()+2;
    	for(int i=1;i<=m;i++){
    		rec[i].x1=lower_bound(u.begin(),u.end(),rec[i].x1)-u.begin()+1;
    		rec[i].x2=lower_bound(u.begin(),u.end(),rec[i].x2)-u.begin()+1;
    		rec[i].y1=lower_bound(v.begin(),v.end(),rec[i].y1)-v.begin()+1;
    		rec[i].y2=lower_bound(v.begin(),v.end(),rec[i].y2)-v.begin()+1;
    		for(int j=rec[i].x1;j<rec[i].x2;j++)for(int k=rec[i].y1;k<rec[i].y2;k++)occ[j][k]=true;
    	}
    	for(int i=1;i<u.size();i++)ae(S,i,u[i]-u[i-1]);
    	for(int i=1;i<v.size();i++)ae(i+u.size(),T,v[i]-v[i-1]);
    	for(int i=1;i<u.size();i++)for(int j=1;j<v.size();j++)if(occ[i][j])ae(i,j+u.size(),0x3f3f3f3f);
    	Dinic();
    	printf("%d\n",res);
    	return 0;
    }
    

  • 相关阅读:
    C#LPT端口连接热敏打印机发送指令
    c# 普通打印机大致有三种方法(非热敏打印机及lpt1并口指令控制型)
    C#直接发送打印机命令到打印机(这里测试的是直接弹出钱箱操作)
    c#操作access,update语句不执行的解决办法
    element-ui dialog组件添加可拖拽位置 可拖拽宽高[转]
    [JavaScript] js实现简单的代码运行框【转】
    HTML5 drag & drop 拖拽与拖放简介[转]
    webpack 单独打包指定JS文件(转)
    跳转地图并定位
    基于Cesium实现逼真的水特效[转]
  • 原文地址:https://www.cnblogs.com/Troverld/p/14610797.html
Copyright © 2011-2022 走看看