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]\),需要满足所有限制且染成红色的盾牌数量最小/最大. 注意到一个盾牌染成红色对于一行和一列都会产生影响.如果选中一个物品对 ...
随机推荐
- jquery 异步请求Demo【转载】
$(document).ready(function() { $.ajax({ url : "/AjaxAction/LoginArea.ashx", data : {userna ...
- HDU5406---CRB and Apple( DP) 2015 Multi-University Training Contest 10
题意比较简单, dp[i][j] 表示上一次男女吃的deliciousness分别为i, j的时候的吃的最多的苹果. 那么dp[i][j] = max(dp[i][k] + 1), 0 < ...
- Java中Websocket使用实例解读
介绍 现在很多网站为了实现即时通讯,所用的技术都是轮询(polling).轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客服端的浏览器 ...
- Ajax之 beforeSend和complete longind制作
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Consolas; min-height: 18.0px } p.p2 { margin: 0 ...
- spring3.1的BeanFactory与Quartz1.8整合
spring的applicationContext.xml配置文件: 加入 <bean id="myJob" class="org.springframework. ...
- angularjs改变路由时控制器每次都执行两次
原因如下: 代码里面也初始化了控制器 模板配置了一个控制器
- VB编写的验证码生成器
验证码(CAPTCHA)是“Completely AutomatedPublicTuring test to tell Computers andHumansApart”(全自动区分计算机和人类的图灵 ...
- Demon_接金币(三个掉落物品预设体,一接物体的工具)
接物体的工具 using UnityEngine; using System.Collections; public class Tool : MonoBehaviour { float hor; V ...
- Android常用ProgressDialog设置
public static ProgressDialog initDialog(Context context) { ProgressDialog progressDialog = new Progr ...
- python Sina微博自动转发带抽奖字样的微博,添加关注,取消关注
项目地址:https://github.com/chengshuyi/SinaWeibo 具有的功能 转发带抽奖字样的微博并可以@相应数量的好友 提取关注并添加关注 取消关注 获取粉丝列表