• CodeForces


    Description

    坐标平面上有 (n) 个点,要给这些点染色,染成红色代价是 (r) ,染成蓝色代价是 (b) 。同时要满足一些条件:

    • (1 l d)(x = l) 的所有点中两种颜色数量差不超过 (d)
    • (2 l d)(y=l) 的所有点中两种颜色数量差不超过 (d)

    问最小代价。

    (n,mle 10^5,1le x,yle 10^9)

    Solution

    这种题一般是先把所有点染成代价高的,然后考虑最多有多少个点能被改成代价低的。

    把每一行和每一列当成节点,对于某个点 ((x,y)) ,就从第 (x) 行连向第 (y​) 列,表示存在这个点。对于那些限制条件就从源/汇点连带有上下界的边。

    要判无解就先跑一个可行流再最大流就行了。

    点数 (2 imes 10^5) ,这题真tm信仰。

    #include<bits/stdc++.h>
    using namespace std;
    
    template <class T> void read(T &x) {
    	x = 0; bool flag = 0; char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar()) flag |= ch == '-';
    	for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - 48; flag ? x = ~x + 1 : 0;
    }
    
    #define N 200010
    #define rep(i, a, b) for (int i = (a); i <= (b); i++)
    #define INF 0x3f3f3f3f
    
    int head[N], cur[N], tot = 1, q[N], dep[N];
    struct edge { int v, c, next; }e[2000010];
    inline void insert(int u, int v, int c) {
    	e[++tot].v = v, e[tot].c = c, e[tot].next = head[u]; head[u] = tot;
    }
    inline void add(int u, int v, int c) { insert(u, v, c), insert(v, u, 0); }
    inline bool bfs(int S, int T) {
    	memset(dep, 0, sizeof dep); dep[S] = 1;
    	int l = 1, r = 1; q[1] = S;
    	while (l <= r) {
    		int u = q[l++];
    		for (int i = head[u], v; i; i = e[i].next) if (e[i].c && !dep[v = e[i].v]) {
    			dep[v] = dep[u] + 1, q[++r] = v;
    			if (v == T) return 1;
    		}
    	}
    	return 0;
    }
    int dfs(int u, int dist, int T) {
    	if (u == T) return dist;
    	int ret = 0;
    	for (int &i = head[u], v; i; i = e[i].next) if (dep[v = e[i].v] == dep[u] + 1 && e[i].c) {
    		int d = dfs(v, min(dist - ret, e[i].c), T);
    		e[i].c -= d, e[i ^ 1].c += d, ret += d;
    		if (ret == dist) return dist;
    	}
    	if (!ret) dep[u] = -1;
    	return ret;
    }
    
    int dinic(int S, int T) {
    	int ret = 0; memcpy(cur, head, sizeof head);
    	while (bfs(S, T)) ret += dfs(S, INF, T), memcpy(head, cur, sizeof cur);
    	return ret;
    }
    
    int x[N], y[N], a[2][N], cnt[2], sum[2][N], pos[N], mx[2][N], mn[2][N], d[N];
    
    inline int get(int x, int y) {
    	return lower_bound(a[y] + 1, a[y] + 1 + cnt[y], x) - a[y];
    }
    
    int main() {
    	int n, m, r, b; read(n), read(m), read(r), read(b);
    	rep(i, 1, n) read(x[i]), read(y[i]), a[0][++cnt[0]] = x[i], a[1][++cnt[1]] = y[i];
    	rep(i, 0, 1) {
    		sort(a[i] + 1, a[i] + 1 + cnt[i]);
    		cnt[i] = unique(a[i] + 1, a[i] + 1 + cnt[i]) - a[i] - 1;
    	}
    	int num = cnt[0] + cnt[1], SS = num + 1, TT = SS + 1, S = TT + 1, T = S + 1;
    	rep(i, 1, n) {
    		sum[0][x[i] = get(x[i], 0)]++, sum[1][y[i] = get(y[i], 1)]++;
    		add(x[i], y[i] + cnt[0], 1), pos[i] = tot - 1;
    	}
    	rep(i, 0, 1) rep(j, 1, cnt[i]) mx[i][j] = sum[i][j];
    	rep(i, 1, m) {
    		int t, l, d; read(t), read(l), read(d); t--;
    		int l1 = get(l, t);
    		if (a[t][l1] != l) continue;
    		mx[t][l1] = min(mx[t][l1], (d + sum[t][l1]) / 2);
    		mn[t][l1] = max(mn[t][l1], (sum[t][l1] - d + 1) / 2);
    		if (mx[t][l1] < mn[t][l1]) { puts("-1"); return 0; }
    	}
    	rep(i, 1, cnt[0]) {
    		add(SS, i, mx[0][i] - mn[0][i]);
    		d[i] += mn[0][i], d[SS] -= mn[0][i];
    	}
    	rep(i, 1, cnt[1]) {
    		add(i + cnt[0], TT, mx[1][i] - mn[1][i]);
    		d[i + cnt[0]] -= mn[1][i], d[TT] += mn[1][i];
    	}
    	add(TT, SS, INF);
    	int sum1 = 0;
    	rep(i, 1, TT) if (d[i] > 0) add(S, i, d[i]), sum1 += d[i]; else add(i, T, -d[i]);
    	int ans = dinic(S, T);
    	if (ans ^ sum1) { puts("-1"); return 0; }
    	ans = dinic(SS, TT);
    	printf("%lld
    ", 1ll * ans * min(r, b) + 1ll * (n - ans) * max(r, b));
    	rep(i, 1, n) putchar(e[pos[i]].c ? (r < b ? 'b' : 'r') : (r < b ? 'r' : 'b'));
    	return 0;
    }
    
    
  • 相关阅读:
    gulp通过http-proxy-middleware开启反向代理,实现跨域
    一些我常用的css 或者 js
    四舍五入
    生成 SSH 公钥
    对象转为数组 用lodash
    廖雪峰的官方网站
    window对象
    字符串
    简单得日期
    LeetCode 113. Path Sum II 20170705 部分之前做了没写的题目
  • 原文地址:https://www.cnblogs.com/aziint/p/9597463.html
Copyright © 2020-2023  润新知