QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#617749 | #5114. Cells Coloring | mhw# | TL | 1ms | 3756kb | C++20 | 3.9kb | 2024-10-06 16:53:06 | 2024-10-06 16:53:07 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
const i64 inf = 2e16;
struct MinCostFlow {
using i64 = long long;
using PII = pair<i64, int>;
const i64 INF = numeric_limits<i64>::max();
struct Edge {
int v, c, f;
Edge(int v, int c, int f) : v(v), c(c), f(f) {}
};
const int n;
vector<Edge> e;
vector<vector<int>> g;
vector<i64> h, dis;
vector<int> pre;
MinCostFlow(int n) : n(n), g(n) {}
void add(int u, int v, int c, int f) {
g[u].push_back(e.size());
e.emplace_back(v, c, f);
g[v].push_back(e.size());
e.emplace_back(u, 0, -f);
}
bool dijstra(int s, int t) {
dis.assign(n, INF);
pre.assign(n, -1);
priority_queue<PII, vector<PII>, greater<PII>> que;
dis[s] = 0;
que.emplace(0, s);
while(!que.empty()) {
auto [d, u] = que.top();
que.pop();
if (dis[u] < d) continue;
for (auto i : g[u])
{
auto [v, c, f] = e[i];
if (c > 0 && dis[v] > d + h[u] - h[v] + f)
{
dis[v] = d + h[u] - h[v] + f;
pre[v] = i;
que.emplace(dis[v], v);
}
}
}
return dis[t] != INF;
}
pair<int, i64> flow(int s, int t)
{
int flow = 0;
i64 cost = 0;
h.assign(n, 0);
while (dijstra(s, t))
{
for (int i = 0; i < n; i++) h[i] += dis[i];
int aug = numeric_limits<int>::max();
for (int i = t; i != s; i = e[pre[i] ^ 1].v) aug = min(aug, e[pre[i]].c);
for (int i = t; i != s; i = e[pre[i] ^ 1].v)
{
e[pre[i]].c -= aug;
e[pre[i] ^ 1].c += aug;
}
flow += aug;
cost += i64(aug) * h[t];
}
return {flow, cost};
}
};
void solve() {
i64 ans = 2e18;
int n, m, c, d, sum = 0;
cin >> n >> m >> c >> d;
vector<string> s(n);
for (int i = 0; i < n; i++) {
cin >> s[i];
}
vector<int> sn(n + 1), sm(m + 1);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (s[i][j] == '.') {
sn[i + 1]++;
sm[j + 1]++;
sum++;
}
}
}
auto cal = [&](int x) -> i64 {
int s = 0, t = n + m + 2;
MinCostFlow cf(n + m + x + 3);
for (int i = 1; i <= n; i++) {
cf.add(0, i, sn[i], 0);
cf.add(i, n + m + 1, sum, d);
}
for (int i = 1; i <= m; i++) {
cf.add(n + i, n + m + 2, sm[i], 0);
cf.add(n + m + 1, n + i, sum, 0);
}
for (int i = 1; i <= x; i++) {
for (int j = 1; j <= n; j++) {
cf.add(j, n + m + 2 + i, 1, 0);
}
for (int j = 1; j <= m; j++) {
cf.add(n + m + 2 + i, n + j, 1, 0);
}
}
auto ans = cf.flow(s, t);
if (ans.first < sum) return inf;
return ans.second + x * c;
};
int l = 1, r = (sum + 1) / 2;
i64 lans, rans;
while (l < r) {
int mid = (l + r) / 2;
int lmid = mid;
int rmid = mid + 1;
lans = cal(lmid), rans = cal(rmid);
ans = min(lans, ans);
ans = min(rans, ans);
// 求凹函数的极小值
if (lans <= rans) r = rmid - 1;
else l = lmid + 1;
// 求凸函数的极大值
if (lans >= rans) l = lmid + 1;
else r = rmid - 1;
}
cout << ans << '\n';
}
signed main(){
ios::sync_with_stdio(0); cin.tie(0), cout.tie(0);
int T = 1;
// cin >> T;
while (T--) solve();
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 1ms
memory: 3756kb
input:
3 4 2 1 .*** *..* **..
output:
4
result:
ok 1 number(s): "4"
Test #2:
score: 0
Accepted
time: 0ms
memory: 3520kb
input:
3 4 1 2 .*** *..* **..
output:
2
result:
ok 1 number(s): "2"
Test #3:
score: -100
Time Limit Exceeded
input:
250 250 965680874 9042302 ..**.*****..**..**.*****..***..***.**......*.***.*...***.*....*.**.*.**.*.*.****...*.******.***.************....**.*..*..***.*******.*.***.*..**..****.**.*.*..***.****..**.....***.....*.****...*...*.***..****..**.*.*******..*.*******.*.*.*.****.*.*** ....**.*******.*.******...