Codeforces 704D Captain America
题意:平面上有n个点,每个点必须涂成红色和蓝色中的一种,花费各为r和b(对所有的点花费都一样).m条限制,每条限制形如”y=b这条直线上两种颜色的点的数目之差的绝对值不能超过c”或” x=b这条直线上两种颜色的点的数目之差的绝对值不能超过c”,点数和限制数10^5,坐标范围10^9.
首先看到坐标范围很大先离散化,然后变成100000*100000的网格图每行每列的限制.那么转化成二分图,原先的每个点转换成边.因为每一行每一列的总点数是已知的,”两种颜色的点的数目之差”就可以转化成红色点和蓝色点的数目范围.接下来不妨把所有点都涂成红色,然后如果蓝色的点比红色的点花费小我们就尽量多涂蓝点,否则尽量少涂蓝点.为了统一问题的形式,在蓝色的点花费小于红色的时候我们就先全涂上蓝色,然后尽量少涂红点.不妨认为现在红色点花费较少,先涂上红点再尽量少涂蓝点.
那么就成了有上下界的网络流问题.对第i行我们建一个点Li,对第j列我们建一个点Ri,从源点向每个Li连一条流量上下界为这一行的蓝色点数目范围的边(在求解蓝点数目范围的时候要考虑到蓝点的数目还应当大于等于0小于等于这一行/列的点数),对每个Ri向汇点连一条流量上下界为这一列的蓝色点数目范围的边,对于坐标为第i行第j列的点,我们从Li向Rj连一条下界为0上界为1的边.跑有上下界的最小流即可.
注意一开始求的蓝点的数目范围可能是空集,这时候直接输出-1,不要再dinic跑可行流了.不知道别人的代码怎么样,反正我的代码很矬,即使有下界>上界的边也能跑出个可行流…
代码稍微长点.
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int maxn=,maxm=; struct edge{ int to,next,w,num; }lst[maxm];int len=,first[maxn],_first[maxn]; void addedge(int a,int b,int w,int num=){ lst[len].num=num; lst[len].to=b;lst[len].next=first[a];lst[len].w=w;first[a]=len++; lst[len].num=num; lst[len].to=a;lst[len].next=first[b];lst[len].w=;first[b]=len++; } int q[maxn],vis[maxn],dis[maxn],s,t,head,tail,T; bool bfs(){ head=tail=;vis[s]=++T;dis[s]=;q[tail++]=s; while(head!=tail){ int x=q[head++]; for(int pt=first[x];pt!=-;pt=lst[pt].next){ if(lst[pt].w&&vis[lst[pt].to]!=T){ vis[lst[pt].to]=T;dis[lst[pt].to]=dis[x]+;q[tail++]=lst[pt].to; } } } if(vis[t]==T)memcpy(_first,first,sizeof(first)); return vis[t]==T; } int dfs(int x,int lim){ if(x==t)return lim; int flow=,a; for(int pt=_first[x];pt!=-;pt=lst[pt].next){ _first[x]=pt; if(lst[pt].w&&dis[lst[pt].to]==dis[x]+&&(a=dfs(lst[pt].to,min(lst[pt].w,lim-flow)))){ lst[pt].w-=a;lst[pt^].w+=a;flow+=a; if(flow==lim)return flow; } } return flow; } int dinic(){ int ans=,x; while(bfs()) while(x=dfs(s,0x7f7f7f7f))ans+=x; return ans; } void del(int x){ for(int pt=first[x];pt!=-;pt=lst[pt].next)lst[pt].w=lst[pt^].w=; } int totflow[maxn]; int bound_flow(){//s-t minimum flow with lowerbound and upperbound int ss=t+,tt=t+; int sum=; for(int i=s;i<=t;++i){ if(totflow[i]<){ addedge(i,tt,-totflow[i]); }else{ sum+=totflow[i]; addedge(ss,i,totflow[i]); } } addedge(t,s,0x7f7f7f7f); int tmps=s,tmpt=t; s=ss;t=tt; if(dinic()!=sum){ printf("-1\n");return -; }else{//return 0; int ans0=lst[len-].w; lst[len-].w=lst[len-].w=; del(ss);del(tt); s=tmpt;t=tmps;//printf("!"); return ans0-dinic(); } } void Add(int a,int b,int lo,int hi,int num=){//printf("%d %d %d %d\n",a,b,lo,hi); totflow[a]-=lo;totflow[b]+=lo; addedge(a,b,hi-lo,num); } int n,m,r,b; int x[maxn],y[maxn],typ[maxn],pos[maxn],delta[maxn]; int lbx[maxn],ubx[maxn],lby[maxn],uby[maxn]; int val[maxn],seq[maxn]; bool cmp(const int &a,const int &b){ return val[a]<val[b]; } int discrete(int x[],int _typ){ int tot=,old=-,cnt=; for(int i=;i<=n;++i){ val[++tot]=x[i]; } for(int i=;i<=m;++i){ if(typ[i]==_typ)val[++tot]=pos[i]; } for(int i=;i<=tot;++i)seq[i]=i; sort(seq+,seq+tot+,cmp); for(int i=;i<=tot;++i){ if(val[seq[i]]!=old){ old=val[seq[i]];++cnt; } val[seq[i]]=cnt; } tot=; for(int i=;i<=n;++i){ x[i]=val[++tot]; } for(int i=;i<=m;++i){ if(typ[i]==_typ)pos[i]=val[++tot]; } return cnt; } int cntx[maxn],cnty[maxn]; int res[maxn]; int main(){ memset(first,-,sizeof(first)); scanf("%d%d",&n,&m); scanf("%d%d",&r,&b); bool reversed = false; if(r>b)swap(r,b),reversed=true; for(int i=;i<=n;++i){ scanf("%d%d",&x[i],&y[i]); } for(int i=;i<=m;++i){ scanf("%d%d%d",typ+i,pos+i,delta+i); } int totx=discrete(x,),toty=discrete(y,); //for(int i=1;i<=n;++i)printf("%d %d\n",x[i],y[i]); //for(int i=1;i<=m;++i)printf("%d %d %d\n",typ[i],pos[i],delta[i]); for(int i=;i<=n;++i)cntx[x[i]]++,cnty[y[i]]++; ll ans=r*1LL*n; for(int i=;i<=totx;++i){ lbx[i]=;ubx[i]=cntx[i]; } for(int i=;i<=toty;++i){ lby[i]=;uby[i]=cnty[i]; } for(int i=;i<=m;++i){ if(typ[i]==){ lbx[pos[i]]=max(lbx[pos[i]],(cntx[pos[i]]-delta[i]+)/);ubx[pos[i]]=min(ubx[pos[i]],(cntx[pos[i]]+delta[i])/); }else{ lby[pos[i]]=max(lby[pos[i]],(cnty[pos[i]]-delta[i]+)/);uby[pos[i]]=min(uby[pos[i]],(cnty[pos[i]]+delta[i])/); } } s=;t=totx+toty+; bool no_solution=false; for(int i=;i<=totx;++i){ Add(s,i,lbx[i],ubx[i]); if(lbx[i]>ubx[i])no_solution=true;//神坑 }//printf("!"); for(int i=;i<=toty;++i){ Add(totx+i,t,lby[i],uby[i]); if(lby[i]>uby[i])no_solution=true;//神坑 }//printf("!"); for(int i=;i<=n;++i){//printf("!"); Add(x[i],totx+y[i],,,i); }//printf("!"); if(no_solution){ printf("-1\n");return ; } int flow=bound_flow(); if(flow!=-){ printf("%lld\n",ans+flow*1LL*(b-r)); for(int i=;i<=totx;++i){ for(int pt=first[i];pt!=-;pt=lst[pt].next){ if(lst[pt].num!=&&lst[pt].w==){ res[lst[pt].num]=; } } }//printf("?"); if(reversed){ for(int i=;i<=n;++i)printf("%c",res[i]?'r':'b'); }else{ for(int i=;i<=n;++i)printf("%c",res[i]?'b':'r'); }printf("\n"); } return ; }
Codeforces 704D Captain America的更多相关文章
- CF#366 704D Captain America 上下界网络流
CF上的题,就不放链接了,打开太慢,直接上题面吧: 平面上有n个点, 第 i 个点的坐标为 ($X_i ,Y_i$), 你需要把每个点染成红色或者蓝色, 染成红色的花费为 r , 染成蓝色的花费为 b ...
- CF 704 D. Captain America
CF 704 D. Captain America 题目链接 题目大意:给出\(n\)个点的坐标,你要将每个点染成红色或者蓝色.染一个红色要付出\(r\)的代价,染一个蓝色要付出\(b\)的代价.有\ ...
- 【CF704D】Captain America(上下界网络流)
[CF704D]Captain America(上下界网络流) 题面 CF 洛谷 题解 如果没有限制,似乎就不用做了...因为我们只需要贪心的选择代价较小的颜色就行了. 那么我们不妨假设染红色的代价较 ...
- CF704D Captain America
http://codeforces.com/problemset/problem/704/D 题解 对于两种颜色的染色,我们可以把它看做选择问题. 比如说红色的代价小,所以我们尽可能多的染红色. 然后 ...
- Codeforces 474C Captain Marmot 给定4个点和各自旋转中心 问旋转成正方形的次数
题目链接:点击打开链接 题意: 给定T表示case数 以下4行是一个case 每行2个点,u v 每次u能够绕着v逆时针转90° 问最少操作多少次使得4个u构成一个正方形. 思路: 枚举判可行 #in ...
- CodeForces 474C Captain Marmot (数学,旋转,暴力)
题意:给定 4n * 2 个坐标,分成 n组,让你判断,点绕点的最少次数使得四个点是一个正方形的顶点. 析:那么就一个一个的判断,n 很小,不会超时,四个点分别从不转然后转一次,转两次...转四次,就 ...
- codeforces704D Captain America【上下界最大流】
分别给行和列hash建两排点,对(x,y)坐标连x行y列的点 设红色价格低,那么就要尽量多选红色 设一个点出度为s,要求最小的最大差值为d,又,假设有流量表示选红没流量表示选蓝,那么要求就变成了这个点 ...
- CF704D Captain America(上下界网络流)
传送门 题意: 二维平面给出\(n\)个点,现在可以给每个点进行染色,染红色的代价为\(r\),染蓝色的代价为\(b\). 之后会有\(m\)个限制,形式如:\(t_i\ l_i\ d_i\),当\( ...
- CF704D Captain America 上下界网络流
传送门 现在相当于说每一个条件都有一个染成红色的盾牌的数量限制\([l,r]\),需要满足所有限制且染成红色的盾牌数量最小/最大. 注意到一个盾牌染成红色对于一行和一列都会产生影响.如果选中一个物品对 ...
随机推荐
- 【二分】Codeforces 706B Interesting drink
题目链接: http://codeforces.com/problemset/problem/706/B 题目大意: n (1 ≤ n ≤ 100 000)个商店卖一个东西,每个商店的价格Ai,你有m ...
- php 环境搭建注意事项
安装php 环境,最后安装集成环境,因为 apache+php 互联不是很容易. 这里主要是两个工具集成工具(wamp ,AppServ),其实这两个集成环境都包括(apache+mysql+php) ...
- Tomcat中server.xml配置及Context的配置说明
server.xml配置简介 下面是这个文件中的基本配置信息,更具体的配置信息见tomcat的文档 server: port 指定一个端口,这个 ...
- 高性能 Socket 组件 HP-Socket v3.2.1-RC5 公布
HP-Socket 是一套通用的高性能 TCP/UDP Socket 组件,包括服务端组件.client组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C+ ...
- android 使用String.format("%.2f",67.876)自已定义语言(俄语、西班牙语)会把小数点变为逗号
市场人员反映公司的app使用系统设置俄语.西班牙语,double数据会把小数点变为逗号.调试一下,是自定义的语言时候(例如,俄语.西班牙语)转换String.format("%.2f&quo ...
- Linux popen/pclose
popen() 函数 #include <stdio.h>FILE * popen(const char *command , const char *type );int pclose( ...
- Ubuntu 14.04 配置vsftpd实现FTP服务器 - 通过FTP连接AWS
测试主机:亚马逊AWS EC2 系统:Ubuntu 14.04 想用AWS来做服务器玩,结果发现其不能像简单使用阿里云服务器那样用ftp连接,反正也不熟悉ftp服务器搭建,那就乘这个机会学习一下如何利 ...
- 配置HP LaserJet M1536dnf MFP打印机通过TCPIP共享多台计算机
HP LaserJet M1536dnf MFP打印机通过TCPIP共享多台计算机配置配置过程:1.确保网线插入到打印机后,点设置按钮,到网络配置中查看IP地址,确保与主机或者路由器的IP地址一致,设 ...
- 递归---NYOJ-90整数划分(一)
这个题理解了好大会才理解,看了网上的代码,不太理解,但是后来看了好几个人的, 大同小异吧,慢慢的就理解了. 思路: 递归函数的意思是, 将 n 划分为最大数为 m 的划分数, 可以分几种情况 1. 当 ...
- 渲染器 Shader BitmapShader
渲染模式: tileX tileY:The tiling mode for x/y to draw the bitmap in. 在位图上 X/Y 方向 瓦工/花砖/瓷砖 模式 CLAMP :如 ...