CF上的题,就不放链接了,打开太慢,直接上题面吧:

平面上有n个点, 第 i 个点的坐标为 ($X_i ,Y_i$), 你需要把每个点
染成红色或者蓝色, 染成红色的花费为 r , 染成蓝色的花费为 b .
有m个限制条件, 有两种类型, 第一种类型为$x = l_i$ 上的红点
与蓝点个数差的绝对值不超过 $d_i$, 第二种类型为$y= l_i$ 上的红
点与蓝点个数差的绝对值不超过 $d_i$.

题解:

  表示这题真的写到失去理想,因为是第一次写带上下限的网络最大流,一开始就把建图和统计代价理解错了好多次。。。

  首先我们可以观察到r, b是固定的,假设r比b小,那么我们就肯定要让涂红色尽可能多,这样才会更优。

  因此我们就不用考虑这个代价了,只需要找到一个合法的方案且使得涂红色的尽可能多即可。

  由于一个点要么涂红,要么涂蓝,因此我们并不需要求出涂蓝的个数,因为只要知道涂红的个数,涂蓝的个数自然就知道了。

  因此现在问题就被简化为了:

    二维平面上有n个点,有m个限制,要求被选中的点尽可能多。

  对于任何一个限制,假设这条线上有num个点,那么我们可以得出被选中点的上限和下限:$[\frac{num - d}{2}, \frac{num + d}{2}]$。

  而对于任何一个点是否被选,也可以看做有一个上限和下限$[0,1]$,即要么不选,要么选一个。
  那么我们将行和列分别用点表示,如果有点(x, y),那么从第x行向第y列连一条[0, 1]的边.

  对于x的限制,从s 到第x行连[下限,上限]的边。

  然后跑带上下限的最大流就可以知道最多选多少点了。

  如何不知道带上下限最大流怎么写请看:算法学习——带上下界网络流

  这题的建图因为还要离散化,所以写起来十分恶心。。。。

  代码比较冗长,建议只看思路。

  (注意在cf上提交的时候只能用I64d,不能用lld)

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 500000
#define ac 2000000
#define inf 2139062143
#define INF 2139062143
#define LL long long int n, m, g, s, t, ss, ff, ww, tt, top1, top2, got, must;
int cnt1, cnt2, x, head, tail, addflow;
int Head[AC], Next[ac], belong[ac], date[ac], haveflow[ac], tot = ;
int lim1_x[AC], lim2_x[AC], lim1_y[AC], lim2_y[AC], q[AC];
int num1[AC], num2[AC], q1[AC], q2[AC], c[AC], have[AC], good[AC], last[AC];
bool z[AC], flag, vis1[AC], vis2[AC];
LL d[AC], ans, red, blue; struct node{
int x, y;
}p[AC]; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} inline void add(int f, int w, int up, int down)
{
belong[tot] = f, date[++tot] = w, Next[tot] = Head[f], Head[f] = tot, haveflow[tot] = up - down, d[f] -= down;
date[++tot] = f, Next[tot] = Head[w], Head[w] = tot, haveflow[tot] = , d[w] += down;
if(w == tt) must += up - down;
// printf("%d ---> %d : %d\n", f, w, up - down);
} inline void upmin(int &a, int b)
{
if(b < a) a = b;
} inline void upmax(int &a, int b)
{
if(b > a) a = b;
} inline int half1(int x)
{
int l = , r = cnt1, mid;
while(l < r)
{
mid = (l + r) >> ;
if(q1[mid] > x) r = mid - ;
else if(q1[mid] < x) l = mid + ;
else return mid;
}
if(q1[l] != x) return ;
else return l;
} inline int half2(int x)
{
int l = , r = cnt2, mid;
while(l < r)
{
mid = (l + r) >> ;
if(q2[mid] > x) r = mid - ;
else if(q2[mid] < x) l = mid + ;
else return mid;
}
if(q2[l] != x) return ;
else return l;
} void link(int x)
{
if(d[x] > ) add(ss, x, d[x], );
else if(d[x] < ) add(x, tt, -d[x], );
} #define c c_
#define d d_ void get_lim()
{
int opt, a, b;
for(R i = ; i <= m; i ++)
{
opt = read(), a = read(), b = read();
if(!a) continue;
if(opt == )//x 的限制
{
a = half1(a);
int c = (num1[a] + b) / , d = (num1[a] - b + ) / ;
if(d > c) {puts("-1"); exit();}//,...这里需要判断
upmin(lim1_x[a], c), upmax(lim1_y[a], d), vis1[a] = true;
}
else
{
a = half2(a);
int c = (num2[a] + b) / , d = (num2[a] - b + ) / ;
if(d > c) {puts("-1"); exit();}
upmin(lim2_x[a], c), upmax(lim2_y[a], d), vis2[a] = true;
}
}
} void pre()
{
n = read(), m = read(), red = read(), blue = read();
s = n + m + , t = s + , ss = t + , tt = ss + ;
memset(lim1_x, , sizeof(lim1_x));
memset(lim2_x, , sizeof(lim2_x));
for(R i = ; i <= n; i ++)
q1[++top1] = p[i].x = read(), q2[++top2] = p[i].y = read();
sort(q1 + , q1 + top1 + );
sort(q2 + , q2 + top2 + );
for(R i = ; i <= top1; i ++)
if(q1[i] != q1[i + ]) q1[++cnt1] = q1[i];
for(R i = ; i <= top2; i ++)
if(q2[i] != q2[i + ]) q2[++cnt2] = q2[i];
g = cnt1, ff = tot + ;
for(R i = ; i <= n; i ++)
{
p[i].x = half1(p[i].x), p[i].y = half2(p[i].y);
add(p[i].x, p[i].y + g, , );
++num1[p[i].x], ++num2[p[i].y];
}
ww = tot;
get_lim();
for(R i = ; i <= cnt1; i ++)
if(vis1[i]) add(s, i, lim1_x[i], lim1_y[i]);
for(R i = ; i <= cnt2; i ++)
if(vis2[i]) add(i + g, t, lim2_x[i], lim2_y[i]);
for(R i = ; i <= n; i ++)
{
if(!vis1[p[i].x])
vis1[p[i].x] = true, add(s, p[i].x, inf, );
if(!vis2[p[i].y])
vis2[p[i].y] = true, add(p[i].y + g, t, inf, );
}
add(t, s, inf, );
link(s), link(t);
for(R i = ; i < s; i ++) link(i);
}
#undef c
#undef d void bfs()
{
int x, now, k = flag ? t : tt;
if(flag) memset(have, , sizeof(have));
if(flag) memset(c, , sizeof(c));
head = tail = ;
q[++tail] = k, c[k] = , have[] = ;
while(head < tail)
{
x = q[++head];
for(R i = Head[x]; i; i = Next[i])
{
now = date[i];
if(flag && (now == ss || now == tt)) continue;
if(!c[now]/* && haveflow[i ^ 1]*/)
{
c[now] = c[x] + ;
q[++tail] = now;
++ have[c[now]];
}
}
}
memcpy(good, Head, sizeof(Head));
} void aru()
{
int k = flag ? s : ss;
while(x != k)
{
//if(flag) printf("%d ---> %d\n", x, date[last[x] ^ 1]);
haveflow[last[x]] -= addflow;
haveflow[last[x] ^ ] += addflow;
x = date[last[x] ^ ];
}
//printf("\n\n");
if(flag) ans += addflow;
else got += addflow;
} void isap()
{
int now; bool done;int k = flag ? t : tt, kk = flag ? s : ss;
addflow = inf, x = kk;
while(c[kk] != k + )
{
if(x == k) aru(), addflow = inf;
done = false;
for(R i = good[x]; i; i = Next[i])
{
now = date[i];
if(flag && (now == ss || now == tt)) continue;
if(c[now] == c[x] - && haveflow[i])
{
upmin(addflow, haveflow[i]);
good[x] = i, last[now] = i;
x = now, done = true;
break;
}
}
if(!done)
{
int go = k + ;
for(R i = Head[x]; i; i = Next[i])
{
now = date[i];
if(flag && (now == ss || now == tt)) continue;
if(haveflow[i] && c[now]) upmin(go, c[now]);
}
if(!(-- have[c[x]])) break;
++have[c[x] = go + ];
good[x] = Head[x];
if(x != kk) x = date[last[x] ^ ];
}
}
} void write(bool k)
{
if(k)
{
if(red < blue) putchar('r');
else putchar('b');
}
else
{
if(red > blue) putchar('r');
else putchar('b');
}
} void find()
{
for(R i = ff; i <= ww; i += ) write(haveflow[i ^ ]);
printf("\n");
} void work()
{
LL k = min(red, blue), kk = max(red, blue);
flag = true;
if(got != must) {puts("-1"); return ;}
bfs();
isap();
ans = k * ans + kk * (n - ans);
printf("%lld\n", ans);
find();
} int main()
{
freopen("in.in", "r", stdin);
pre();
bfs();
isap();
work();
fclose(stdin);
return ;
}

CF#366 704D Captain America 上下界网络流的更多相关文章

  1. CF704D Captain America 上下界网络流

    传送门 现在相当于说每一个条件都有一个染成红色的盾牌的数量限制\([l,r]\),需要满足所有限制且染成红色的盾牌数量最小/最大. 注意到一个盾牌染成红色对于一行和一列都会产生影响.如果选中一个物品对 ...

  2. 【CF704D】Captain America(上下界网络流)

    [CF704D]Captain America(上下界网络流) 题面 CF 洛谷 题解 如果没有限制,似乎就不用做了...因为我们只需要贪心的选择代价较小的颜色就行了. 那么我们不妨假设染红色的代价较 ...

  3. CF 704 D. Captain America

    CF 704 D. Captain America 题目链接 题目大意:给出\(n\)个点的坐标,你要将每个点染成红色或者蓝色.染一个红色要付出\(r\)的代价,染一个蓝色要付出\(b\)的代价.有\ ...

  4. hdu 4940 Destroy Transportation system( 无源汇上下界网络流的可行流推断 )

    题意:有n个点和m条有向边构成的网络.每条边有两个花费: d:毁坏这条边的花费 b:重建一条双向边的花费 寻找这样两个点集,使得点集s到点集t满足 毁坏全部S到T的路径的费用和 > 毁坏全部T到 ...

  5. ACM-ICPC 2018 沈阳赛区网络预赛 F Fantastic Graph(贪心或有源汇上下界网络流)

    https://nanti.jisuanke.com/t/31447 题意 一个二分图,左边N个点,右边M个点,中间K条边,问你是否可以删掉边使得所有点的度数在[L,R]之间 分析 最大流不太会.. ...

  6. 算法笔记--最大流和最小割 && 最小费用最大流 && 上下界网络流

    最大流: 给定指定的一个有向图,其中有两个特殊的点源S(Sources)和汇T(Sinks),每条边有指定的容量(Capacity),求满足条件的从S到T的最大流(MaxFlow). 最小割: 割是网 ...

  7. POJ 2396 Budget(有源汇上下界网络流)

    Description We are supposed to make a budget proposal for this multi-site competition. The budget pr ...

  8. HDU 4940 Destroy Transportation system(无源汇上下界网络流)

    Problem Description Tom is a commander, his task is destroying his enemy’s transportation system. Le ...

  9. ACM-ICPC 2018 沈阳赛区网络预赛 F. Fantastic Graph (贪心或有源汇上下界网络流)

    "Oh, There is a bipartite graph.""Make it Fantastic."X wants to check whether a ...

随机推荐

  1. php 微信客服信息推送失败 微信重复推送客服消息 40001 45047

    /*** * 微信客服发送信息 * 微信客服信息推送失败 微信重复推送客服消息 40001 45047 * 递归提交到微信 直到提交成功 * @param $openid * @param int $ ...

  2. MIP组件开发 自定义js组件开发步骤

    什么是百度MIP? MIP(Mobile Instant Pages - 移动网页加速器)主要用于移动端页面加速 官网参考:https://www.mipengine.org/doc/00-mip-1 ...

  3. Python基于jieba的中文词云

    今日学习了python的词云技术 from os import path from wordcloud import WordCloud import matplotlib.pyplot as plt ...

  4. JAVA 泛型方法<T>

    public static void main(String[] args) throws Exception { String[] arr = new String[]{"1", ...

  5. shell重温---基础篇(参数传递&echo命令)

    经过前两天的学习,关于shell的基础算是知道的一般般啦,最起码不算是小白了(纯属意淫).今天就来点干货哈.   首先是运行shell脚本时的参数传递.脚本内获取参数的格式为$n.n代表了一个数字,例 ...

  6. oracle 11g XE 学习版添加scott用户方法全步骤

    安装企业版的orcale是不是太费时费力了?若只是学习用途的话,不妨试试轻便版的XE版本,同样是官网下载的,但是这个安装起来比完整版简便多了. 首先,你得先安装好orcale 11g XE 版本:(这 ...

  7. 环境变量 - JDK

    Linux 1. 备份并编辑配置文件 # cp /etc/profile /etc/profile.bak # vi /etc/profile 2. 设置JDK环境变量 export JAVA_HOM ...

  8. 使用Visual Studio 2017构建.Net Core的Docker镜像

    1 Docker  镜像优化 微软在为开发人员生成 Docker 镜像时,提供以下三种主要方案: 用于开发 .NET Core 应用的 镜像 用于构建生成 .NET Core 应用的 镜像 用于运行 ...

  9. 纯js生成QRCode

    纯js,不依赖jquery,非常好用,废话不多说,直接上代码! <!DOCTYPE html> <html> <head> <meta charset=&qu ...

  10. CSS实现简易的轮播图

    <html> <head> <meta charset="UTF-8"> <title></title> <sty ...