传送门

题意:

二维平面给出\(n\)个点,现在可以给每个点进行染色,染红色的代价为\(r\),染蓝色的代价为\(b\)。

之后会有\(m\)个限制,形式如:\(t_i\ l_i\ d_i\),当\(t_i=1\)时,表示\(l_i\)行两种颜色的点数相差不超过\(d_i\);类似地,当\(t_i=2\)时表示的是列时的状态。

问最终怎么染色代价最小且符合限制条件。

思路:

  • 带上下界的网络流。
  • 我们不妨设\(r<b\),那么肯定是红点越多越好。我们找准最大这个数量关系,然后考虑最大流。
  • 建图方式为:左右两排分别表示行和列,中间则为每个点,源点和左排相连带有上下界,汇点和右排相连带有上下界。
  • 上下界很好推,假设第\(i\)行共\(tot_i\)个点,我们选\(x\)个红点,那么就有:\(|x-(tot - x)|\leq d\),绝对值打开化简即可得到\(x\)的范围,若一个满足范围,另一个点也必然满足范围。
  • 为什么要在两排中间加上点?因为我们最后要输出方案,我们需要根据流过点的流量来判断这个点是否染色。

这种有源有汇最大流,首先转化为无源无汇最大流,得到\(s\)到\(t\)的可行流,最后去掉附加点和边,最后再从\(s\)到\(t\)跑一次最大流,两次的答案加起来即可得到答案。

注意进入流量若大于出度流量,我们连接源点向它来补充这多出来的。

详见代码:

#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 5e5 + 5; #define INF 0x3f3f3f3f
int s, t, SS, TT;
int n, m, r, b, f;
void Fail() {
cout << -1 << '\n';
exit(0);
}
template <class T>
struct Dinic{
struct Edge{
int v, next;
T flow;
Edge(){}
Edge(int v, int next, T flow) : v(v), next(next), flow(flow) {}
}e[N << 1];
int head[N], tot;
int dep[N], M[N];
int all;
void init() {
memset(head, -1, sizeof(head)); tot = 0;
}
void adde(int u, int v, T down, T up) {
if(up < down) Fail();
e[tot] = Edge(v, head[u], up - down);
head[u] = tot++;
e[tot] = Edge(u, head[v], 0);
head[v] = tot++;
M[u] -= down; M[v] += down;
}
void adde() {
for(int i = 0; i <= t; i++) {
if(M[i] > 0) adde(SS, i, 0, M[i]);
else if(M[i] < 0) adde(i, TT, 0, -M[i]);
}
adde(t, s, 0, INF);
}
bool BFS(int _S, int _T) {
memset(dep, 0, sizeof(dep));
queue <int> q; q.push(_S); dep[_S] = 1;
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if(!dep[v] && e[i].flow > 0) {
dep[v] = dep[u] + 1;
q.push(v);
}
}
}
return dep[_T] != 0;
}
T dfs(int _S, int _T, T a) {
T flow = 0, f;
if(_S == _T || a == 0) return a;
for(int i = head[_S]; ~i; i = e[i].next) {
int v = e[i].v;
if(dep[v] != dep[_S] + 1) continue;
f = dfs(v, _T, min(a, e[i].flow));
if(f) {
e[i].flow -= f;
e[i ^ 1].flow += f;
flow += f;
a -= f;
if(a == 0) break;
}
}
if(!flow) dep[_S] = -1;
return flow;
}
T dinic(int _S, int _T) {
T max_flow = 0;
while(BFS(_S, _T)) max_flow += dfs(_S, _T, INF);
return max_flow;
}
T work() {
int tmp = dinic(SS, TT);
for(int i = head[SS]; i != -1; i = e[i].next) {
if(e[i].flow) Fail();
}
int ans = e[tot - 1].flow;
e[tot - 1].flow = e[tot - 2].flow = 0;
for(int i = head[SS]; i != -1; i = e[i].next) {
e[i].flow = e[i ^ 1].flow = 0;
}
for(int i = head[TT]; i != -1; i = e[i].next) {
e[i].flow = e[i ^ 1].flow = 0;
}
ans += dinic(s, t);
return ans;
}
//f = 1 -> r > b;
void Print(int f, int L, int R) {
for(int i = L + 1; i <= L + n; i++) {
bool flag = false;
for(int j = head[i]; j != -1; j = e[j].next) {
int v = e[j].v;
if(e[j].flow == 0 && v > n + L && v <= n + L + R) {
flag = true;
cout << (f == 1 ? 'b' : 'r');
}
}
if(!flag) cout << (f == 1 ? 'r' : 'b');
}
}
};
Dinic <int> solver;
int x[N], y[N], X[N], Y[N];
int mxx[N], mxy[N], cntx[N], cnty[N];
void Hash(int *a, int *b, int &c) {
sort(b + 1, b + n + 1);
c = unique(b + 1, b + n + 1) - b - 1;
for(int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + c + 1, a[i]) - b;
}
void Hash(int &a, int &b) {
Hash(x, X, a); Hash(y, Y, b);
}
void run() {
cin >> r >> b;
if(r >= b) {
f = 1;
swap(r, b);
}
solver.init();
for(int i = 1; i <= n; i++) {
cin >> x[i] >> y[i];
X[i] = x[i], Y[i] = y[i];
}
int lx, ly;
Hash(lx, ly);
dbg(lx, ly);
s = 0, t = lx + ly + n + 1;
SS = t + 1, TT = t + 2;
for(int i = 1; i <= n; i++) {
solver.adde(x[i], lx + i, 0, 1);
solver.adde(lx + i, y[i] + n + lx, 0, 1);
}
for(int i = 1; i <= lx; i++) mxx[i] = n;
for(int i = 1; i <= ly; i++) mxy[i] = n;
for(int i = 1; i <= m; i++) {
int t, l, d; cin >> t >> l >> d;
if(t & 1) {
int p = lower_bound(X + 1, X + lx + 1, l) - X;
if(X[p] != l) continue;
else mxx[p] = min(mxx[p], d);
}
else {
int p = lower_bound(Y + 1, Y + ly + 1, l) - Y;
if(Y[p] != l) continue;
else mxy[p] = min(mxy[p], d);
}
}
for(int i = 1; i <= n; i++) ++cntx[x[i]];
for(int i = 1; i <= n; i++) ++cnty[y[i]];
for(int i = 1; i <= lx; i++) {
if(cntx[i] <= mxx[i]) solver.adde(s, i, 0, INF);
else solver.adde(s, i, (cntx[i] - mxx[i] + 1) / 2, (cntx[i] + mxx[i]) / 2);
}
for(int i = 1; i <= ly; i++) {
if(cnty[i] <= mxy[i]) solver.adde(n + lx + i, t, 0, INF);
else solver.adde(n + lx + i, t, (cnty[i] - mxy[i] + 1) / 2, (cnty[i] + mxy[i]) / 2);
}
solver.adde();
int flow = solver.work();
cout << 1ll * flow * r + 1ll * (n - flow) * b << '\n';
solver.Print(f, lx, ly);
} int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
#ifdef Local
freopen("../input.in", "r", stdin);
freopen("../output.out", "w", stdout);
#endif
while(cin >> n >> m) run();
return 0;
}

最新文章

  1. archlinux安裝手记(Win10+Arch、GPT+UEFI、lvm)
  2. tomcat:there is no resources that can be added or removed from server
  3. Java进击C#——项目开发环境
  4. [codevs2181]田忌赛马
  5. android ImageView的属性android:scaleType,即ImageView.setScaleType(ImageView.ScaleType)
  6. HDU2227Find the nondecreasing subsequences(树状数组+DP)
  7. 【学习笔记】【C语言】变量
  8. IOS9任务管理器特效的实现
  9. JAVA基础---编码解码
  10. 系统引导修复 ---- Windows 和 Ubuntu
  11. 回顾一下shell脚本1
  12. java之SpringMVC配置!配置!配置!
  13. Nano Server速记
  14. pyspider爬虫框架webui简介-爬取阿里招聘信息
  15. .net Core 生产环境报错 MIME
  16. 【ApplicationListener】Springboot各类事件监听器
  17. MySQL查询表的所有列名,用逗号拼接
  18. Studying GIT
  19. jquery操作select(取值,设置选中)(转)
  20. web window pixel等笔记

热门文章

  1. 日志分析利器Splunk的搭建、使用、破解
  2. java调用含第三方库的py文件
  3. Django 连接数据库
  4. 使用CMD命令部署.NetCore程序到IIS
  5. mysql事务隔离级别与设置
  6. 【shell脚本】定时备份数据库===dbbackup.sh
  7. 解决centos ssh连接很慢的问题
  8. 【Oracle】 RMAN命令汇总
  9. NoSql之Redis系列(.Net Core)
  10. Unsupervised Attention-guided Image-to-Image Translation