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]\),需要满足所有限制且染成红色的盾牌数量最小/最大. 注意到一个盾牌染成红色对于一行和一列都会产生影响.如果选中一个物品对 ...
 
随机推荐
- fastjson将bean转成字符串时首字母变小写问题
			
一个项目需求要求返回值为JSON格式,且大多数字段是首字母大写,还有些是类似N_TX这样的格式,在输出这样的结果时遇到了问题,由于时间紧,就直接拷贝需要的结果字段建立JavaBean类,本以为最后直接 ...
 - Nginx+Keepalived主备切换(包含nginx服务停止)
			
原文地址:http://blog.sina.com.cn/s/blog_79ac6aa80101bmed.html Nginx+Keepalived主备切换(包含nginx服务停止) 环境: VM中4 ...
 - [Java] 模板引擎 Velocity 随笔
			
Velocity 是一个基于 Java 的模板引擎. 本博文演示 Velocity 的 HelloWord 以及分支条件. HelloWord.vm,模板文件. templateDemo.java, ...
 - Spark Streaming 入门指南
			
这篇博客帮你开始使用Apache Spark Streaming和HBase.Spark Streaming是核心Spark API的一个扩展,它能够处理连续数据流. Spark Streaming是 ...
 - M - Escape - HDU 3605 - (缩点+最大流SAP)
			
题目大意:2012世界末日来了,科学家发现了一些星球可以转移人口,不过有的人可以在一些星球上生存有的人不行,而且每个星球都有一定的承载量,现在想知道是否所有的人都可以安全转移呢? 输入:首先输入一个N ...
 - Unity3D基础学习 NGUI之Example 13 - Tabs简要概述
			
首先建一个2D相机,在Anchor下新建一个子物体,添加WindowDrag Tilt脚本,用作拖动窗口 然后新建一个Panel,包含两个content,两个Tab,设置两个Content用来显示切换 ...
 - [Javascript] Add a browser build to an npm module
			
In this lesson, we're going to use webpack to create a UMD (Universal Module Definition) build of ou ...
 - [RxJS] Combining streams in RxJS
			
Source: Link We will looking some opreators for combining stream in RxJS: merge combineLatest withLa ...
 - [CSS3 + HTML5] Modernizr
			
Modernizr is a library for detecting whether the user's browsers have certain features and based on ...
 - atitit。浏览器缓存机制 and 微信浏览器防止缓存的设计 attilax 总结
			
atitit.浏览器缓存机制 and 微信浏览器防止缓存的设计 attilax 总结 1. 缓存的一些机制 1 1.1. http 304 1 1.2. 浏览器刷新的处理机制 1 1.3. Expir ...