21nc3-c Minimum grid

news/2025/2/12 0:46:34/

题面

题意

  • 有一个 n × n n\times n n×n 的矩阵, m m m 个点可以填数,给定两个数组 r r r c c c r [ i ] r[i] r[i] 表示第 i i i 行的最大元素, c [ i ] c[i] c[i] 表示第 i i i 列的最大元素,需要在这 m m m 个点中填值,在满足 r r r c c c 数组的条件下求矩阵最小和。
  • 1 ≤ n ≤ 2 × 1 0 3 , 1 ≤ m ≤ 8 × 1 0 5 , 1 ≤ k ≤ 1 0 6 , 1 ≤ b i , c i ≤ k 1\le n\le 2\times 10^3,1\le m\le 8\times10^5,1\le k\le 10^6,1\le b_i,c_i\le k 1n2×103,1m8×105,1k106,1bi,cik b i , c i b_i,c_i bi,ci 最多有 500 个值

思路

  1. 考虑到每一种 b i , c i b_i,c_i bi,ci 独立,只有 b i = c i b_i=c_i bi=ci 才能减少答案,此时行列共用一个最大值。将行与列抽象成二分图的两边的点。 b i = c i b_i=c_i bi=ci 时两个点连一条边,因为每一行与每一列连一条边后不能再连边减少答案,这就是二分图的性质,所以现在等价于求二分图的最大匹配。考虑所有 b i = c i b_i=c_i bi=ci 的情况,分别建图跑最大流即可。

代码

const int N = 2e3 + 5, M = 1e6;ll ans;
int row[N], col[N];
int n, m, k, S, T, f[M];
int h[N], e[M], ne[M], idx;
int d[N], cur[N];
bool vis[N][N];
vi tr[M], tc[M];void add(int u, int v, int c) {e[idx] = v, f[idx] = c, ne[idx] = h[u], h[u] = idx++;e[idx] = u, f[idx] = 0, ne[idx] = h[v], h[v] = idx++;
}void init() {mst(h, -1); idx = 0;}void inp() {init();cin >> n >> m >> k;S = N - 2, T = N - 1;rep(i, 1, n) row[i] = rd, tr[row[i]].pb(i);rep(i, 1, n) col[i] = rd, tc[col[i]].pb(i);rep(i, 1, m) {int u = rd, v = rd;vis[u][v] = true;}
}bool bfs() {queue<int> q;mst(d, -1);q.push(S), d[S] = 0, cur[S] = h[S];while(!q.empty()) {int u = q.front(); q.pop();for(int i = h[u]; ~i; i = ne[i]) {int v = e[i];if(d[v] == -1 && f[i]) {d[v] = d[u] + 1;cur[v] = h[v];if(v == T) return true;q.push(v);}}}return false;
}int find(int u, int limit) {if(u == T) return limit;int flow = 0;for(int i = cur[u]; ~i && flow < limit; i = ne[i]) {int v = e[i];cur[u] = i;if(d[v] == d[u] + 1 && f[i]) {int t = find(v, min(f[i], limit - flow));if(!t) d[v] = -1;f[i] -= t, f[i ^ 1] += t, flow += t;}}return flow;
}int dinic() {int ret = 0, flow = 0;while(bfs()) {while(1) {flow = find(S, inf); ret += flow;if(!flow) break;}}return ret;
}int main() {inp();per(i, k, 1) {init();int dx = sz(tr[i]);for(int ele : tr[i]) add(S, ele, 1);for(int ele : tc[i]) add(ele + dx, T, 1);for(int ele1 : tr[i]) for(int ele2 : tc[i])if(vis[ele1][ele2]) add(ele1, ele2 + dx, 1);ans += (ll)(sz(tr[i]) + sz(tc[i]) - dinic()) * i;}cout << ans << endl;return 0;
}

http://www.ppmy.cn/news/536271.html

相关文章

yb3防爆电机型号含义_YBK3/YB3/YBX3-160M2-2-15KW防爆电机参数详解

YBK3/YB3/YBX3-160M2-2-15KW防爆电机功率为90KW,转速在2930左右&#xff0c;效率91.9%&#xff0c;功率因数0.88&#xff0c;电流在380V时为28.18A,额定转矩48.89(Nm)堵转转矩2.0Nm&#xff0c;最大转矩2.3m。噪声82Lw/74Lp&#xff0c;转动惯量0.31kg.m2 YBK3/YB3/YBX3-160M2-…

CF 1C

题目大意是给出正多边形上的三个点坐标, 求这个正多边形的面积. 由于是确定是正多边形,所以一定存在外接圆.所以可以分为如下几步: 海伦公式: p(abc)/2 S√p(p-a)(p-b)(p-c) 1.求外接圆半径rabc/4S 2.由余弦定理求出三个圆心角ang[3] (要注意的是,有可能有三个点在同一段半…

CF 13C

给定一个序列&#xff0c;可以对其中元素进行加一或者减一的操作&#xff0c;问最少多少次操作可以将其转换成非降序列 dp[i][j]表示把前i个数变成非降序列&#xff0c;并且第i个数变成原序列中从小到大第j个数所用的最少步数。 dp[i][j]min(dp[i-1][j]abs(a[i]-b[j]),dp[i][…

cf 1332c

题意&#xff1a; 定义s串是“k组合串”&#xff0c;当且仅当s是回文串且s等于k个一模一样的子串相连接&#xff0c; 比如s abaaba,则s是"3组合串"&#xff0c;给你个字符串&#xff0c;问你最少改多少个字符把它变成“k组合串” 输入 4 //表示4组样例 6 2 //s长度…

CF1129A2 Toy Train

当一个车站如果有最多的糖果数x&#xff0c;那么跑x-1圈就能让前面x-1个糖果放到相应的地方&#xff0c;如果想让这时候跑的站数最少&#xff0c;那么最后一个应该放最近的糖果。 如果当前这个车站a并不是最多的糖果数&#xff0c;但是要跑的最少站数取决于拥有最多糖果数的站…

JS12

12 BOM Broswer Object Model 12.1 常用对象 window&#xff08;窗口&#xff09;&#xff0c;浏览器的窗口 var a 1; function test(){ var a 2; alert(a); alert(window.a); } 全局变量window的属性&#xff0c;全局函数window的方法 浏览器body的宽度&a…

js2c#

http://www.m2h.nl/files/js_to_c.php