QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#454569 | #6546. Greedy Bipartite Matching | pandapythoner | TL | 979ms | 107012kb | C++20 | 9.7kb | 2024-06-25 04:23:27 | 2024-06-25 04:23:28 |
Judging History
answer
#pragma GCC optimize("Ofast,unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define flt double
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define rep(i, n) for(int i = 0; i < n; i += 1)
const ll inf = 1e18;
mt19937 rnd(234);
struct num {
vector<pair<int, int>> a;
num() {}
num(int x, int y) {
a = { make_pair(x, y) };
}
bool is_zero() {
return a.empty();
}
bool is_nonnegative() {
if (a.empty()) {
return true;
}
return a[0].second > 0;
}
bool is_negative() {
return !is_nonnegative();
}
};
num operator+(const num& a, const num& b) {
num c;
c.a.reserve((int)a.a.size() + (int)b.a.size());
int i = 0, j = 0;
while (i < (int)a.a.size() and j < (int)b.a.size()) {
if (a.a[i].first < b.a[j].first) {
c.a.push_back(a.a[i]);
i += 1;
} else if (a.a[i].first > b.a[j].first) {
c.a.push_back(b.a[j]);
j += 1;
} else if (a.a[i].second + b.a[j].second != 0) {
c.a.push_back(make_pair(a.a[i].first, a.a[i].second + b.a[j].second));
i += 1;
j += 1;
} else {
i += 1;
j += 1;
}
}
while (i < (int)a.a.size()) {
c.a.push_back(a.a[i]);
i += 1;
}
while (j < (int)b.a.size()) {
c.a.push_back(b.a[j]);
j += 1;
}
return c;
}
num operator-(const num& a, const num& b) {
num c;
c.a.reserve((int)a.a.size() + (int)b.a.size());
int i = 0, j = 0;
while (i < (int)a.a.size() and j < (int)b.a.size()) {
if (a.a[i].first < b.a[j].first) {
c.a.push_back(a.a[i]);
i += 1;
} else if (a.a[i].first > b.a[j].first) {
c.a.push_back(make_pair(b.a[j].first, -b.a[j].second));
j += 1;
} else if (a.a[i].second - b.a[j].second != 0) {
c.a.push_back(make_pair(a.a[i].first, a.a[i].second - b.a[j].second));
i += 1;
j += 1;
} else {
i += 1;
j += 1;
}
}
while (i < (int)a.a.size()) {
c.a.push_back(a.a[i]);
i += 1;
}
while (j < (int)b.a.size()) {
c.a.push_back(b.a[j]);
j += 1;
}
return c;
}
bool operator<(const num& a, const num& b) {
int i = 0, j = 0;
while (i < (int)a.a.size() and j < (int)b.a.size()) {
if (a.a[i].first < b.a[j].first) {
return (a.a[i].second < 0);
} else if (a.a[i] > b.a[j]) {
return (b.a[j].second > 0);
} else if (a.a[i].second - b.a[j].second != 0) {
return a.a[i].second < b.a[j].second;
}
i += 1;
j += 1;
}
if (i < (int)a.a.size()) {
return a.a[i].second < 0;
}
if (j < (int)b.a.size()) {
return b.a[i].second > 0;
}
return false;
}
struct edge {
int to;
num w;
int f, c;
int rvi;
edge() {}
edge(int to, const num& w, int c, int rvi) : to(to), w(w), f(0), c(c), rvi(rvi) {}
int rest() const {
return c - f;
}
};
namespace flow {
int n;
int q;
vector<vector<edge>> g;
void build(int _n, int _q) {
n = _n;
q = _q;
g.assign(n, vector<edge>());
}
void add_edge(int v, int to, int x = -1) {
int i = (int)g[v].size();
int j = (int)g[to].size();
if (x == -1) {
g[v].push_back(edge(to, num(), 1, j));
g[to].push_back(edge(v, num(), 0, i));
} else {
g[v].push_back(edge(to, num(x, -1), 1, j));
g[to].push_back(edge(v, num(x, 1), 0, i));
}
}
vector<num> dist;
vector<int> usd;
void dijkstra(int s) {
dist.assign(n, num(-1, 1));
dist[s] = num();
usd.assign(n, false);
usd[s] = true;
set<pair<num, int>> q;
q.insert(make_pair(dist[s], s));
while (!q.empty()) {
int v = q.begin()->second;
usd[v] = true;
q.erase(q.begin());
for (auto& e : g[v]) {
int to = e.to;
if (usd[to] or e.rest() <= 0) {
continue;
}
if (dist[v] + e.w < dist[to]) {
if (dist[to].a.empty() or dist[to].a[0].first != -1) {
q.erase(make_pair(dist[to], to));
}
dist[to] = dist[v] + e.w;
q.insert(make_pair(dist[to], to));
}
}
}
}
vector<int> pntr;
vector<int> dist_bfs;
void bfs(int s) {
dist_bfs.assign(n, n + 10);
dist_bfs[s] = 0;
queue<int> q;
q.push(s);
while (!q.empty()) {
int v = q.front();
q.pop();
for (auto& e : g[v]) {
int to = e.to;
if (e.rest() <= 0 or !e.w.is_zero()) {
continue;
}
if (dist_bfs[to] > dist_bfs[v] + 1) {
dist_bfs[to] = dist_bfs[v] + 1;
q.push(to);
}
}
}
}
bool dfs1(int v, int t) {
if (v == t) {
return true;
}
usd[v] = true;
for (int& i = pntr[v]; i < (int)g[v].size(); i += 1) {
auto& e = g[v][i];
int to = e.to;
if (usd[to] or e.rest() <= 0 or !e.w.is_zero() or dist_bfs[to] != dist_bfs[v] + 1) {
continue;
}
if (dfs1(to, t)) {
e.f += 1;
g[to][e.rvi].f -= 1;
usd[v] = false;
return true;
}
}
return false;
}
bool dfs2(int v, int t) {
if (v == t) {
return true;
}
usd[v] = true;
for (int& i = pntr[v]; i < (int)g[v].size(); i += 1) {
auto& e = g[v][i];
int to = e.to;
if (usd[to] or e.rest() <= 0 or !e.w.is_zero()) {
continue;
}
if (dfs2(to, t)) {
e.f += 1;
g[to][e.rvi].f -= 1;
usd[v] = false;
return true;
}
}
return false;
}
vector<int> topsort;
void dfs_topsort(int v) {
usd[v] = true;
for (auto& e : g[v]) {
int to = e.to;
if (usd[to] or e.rest() <= 0) {
continue;
}
dfs_topsort(to);
}
topsort.push_back(v);
}
vector<int> flow(int s, int t) {
num delta = num();
topsort.clear();
usd.assign(n, false);
dfs_topsort(s);
reverse(all(topsort));
dist.assign(n, num(-1, 1));
dist[s] = num();
for (auto v : topsort) {
for (auto& e : g[v]) {
int to = e.to;
if (e.rest() <= 0) {
continue;
}
if (dist[v] + e.w < dist[to]) {
dist[to] = dist[v] + e.w;
}
}
}
auto relax = [&]() {
delta = delta + dist[t];
rep(v, n) {
if (!usd[v]) {
continue;
}
for (auto& e : g[v]) {
int to = e.to;
if (!usd[to]) {
continue;
}
e.w = e.w + dist[v] - dist[to];
}
}
};
relax();
vector<int> result(q);
int iters = 0;
while (1) {
iters += 1;
assert(iters <= 1000);
dijkstra(s);
if (!usd[t]) {
break;
}
relax();
if (delta.is_nonnegative()) {
break;
}
assert((int)delta.a.size() == 1);
bfs(s);
pntr.assign(n, 0);
usd.assign(n, false);
while (1) {
bool ok = dfs1(s, t);
if (!ok) {
break;
}
result[delta.a[0].first] += -delta.a[0].second;
}
pntr.assign(n, 0);
usd.assign(n, false);
while (1) {
bool ok = dfs2(s, t);
if (!ok) {
break;
}
result[delta.a[0].first] += -delta.a[0].second;
}
}
for (int i = 1; i < q; i += 1) {
result[i] += result[i - 1];
}
return result;
}
};
int32_t main() {
if (1) {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int n, q;
cin >> n >> q;
flow::build(2 * n + 2, q);
rep(i, n) {
flow::add_edge(2 * n, i);
flow::add_edge(n + i, 2 * n + 1);
}
rep(i, q) {
int t;
cin >> t;
rep(j, t) {
int u, v;
cin >> u >> v;
--u;
--v;
flow::add_edge(u, n + v, i);
}
}
auto result = flow::flow(2 * n, 2 * n + 1);
assert((int)result.size() == q);
rep(i, q) {
cout << result[i] << " ";
}
cout << "\n";
return 0;
}
/*
3 4
2
1 1
1 2
2
1 1
2 2
2
1 3
3 2
1
3 3
*/
詳細信息
Test #1:
score: 100
Accepted
time: 0ms
memory: 3868kb
input:
3 4 2 1 1 1 2 2 1 1 2 2 2 1 3 3 2 1 3 3
output:
1 2 2 3
result:
ok 4 number(s): "1 2 2 3"
Test #2:
score: 0
Accepted
time: 0ms
memory: 3668kb
input:
0 0
output:
result:
ok 0 number(s): ""
Test #3:
score: 0
Accepted
time: 0ms
memory: 3880kb
input:
2 2 0 2 1 2 1 2
output:
0 1
result:
ok 2 number(s): "0 1"
Test #4:
score: 0
Accepted
time: 931ms
memory: 99660kb
input:
100000 1 200000 78475 45796 32145 46393 92550 13904 73461 34145 96461 92851 56319 77067 77530 84437 76343 51543 77507 99269 76411 89382 1779 61393 43608 96136 84269 74828 14858 35967 32085 94909 19877 175 1482 94391 12424 55020 64369 92588 81296 7903 25433 46033 36294 61129 73556 84837 8419 10215 12...
output:
100000
result:
ok 1 number(s): "100000"
Test #5:
score: 0
Accepted
time: 953ms
memory: 101492kb
input:
100000 1 200000 56816 52517 2577 76202 40378 1758 50464 66497 15834 50880 9829 16331 80693 9963 51096 17591 15871 35192 91302 65510 90775 57493 11891 8967 44787 41896 3387 35479 93471 47453 84804 93636 90746 34877 18202 38718 7473 34258 36581 19533 13249 27525 6442 69870 8822 61871 94537 67714 41396...
output:
100000
result:
ok 1 number(s): "100000"
Test #6:
score: 0
Accepted
time: 0ms
memory: 3608kb
input:
4 1 7 2 2 3 3 1 1 4 2 2 3 3 1 4 3
output:
3
result:
ok 1 number(s): "3"
Test #7:
score: 0
Accepted
time: 390ms
memory: 90412kb
input:
100000 1 199999 25371 25371 85965 85964 416 416 16797 16797 12438 12438 45410 45409 63006 63005 22156 22156 87829 87828 84014 84014 37308 37308 72325 72325 83704 83704 55391 55390 6781 6780 78091 78091 9376 9376 82193 82193 74695 74695 49842 49842 15799 15799 69856 69855 82949 82948 97390 97389 205 ...
output:
100000
result:
ok 1 number(s): "100000"
Test #8:
score: 0
Accepted
time: 358ms
memory: 90668kb
input:
100000 1 199999 59470 59470 76774 76773 89517 89517 87041 87041 90185 90185 83076 83076 61455 61455 33616 33616 85795 85794 92073 92072 49726 49726 63843 63842 99248 99248 24122 24122 29553 29552 73534 73534 75846 75846 27030 27029 84419 84419 26637 26637 10101 10100 75014 75013 67342 67342 75647 75...
output:
100000
result:
ok 1 number(s): "100000"
Test #9:
score: 0
Accepted
time: 939ms
memory: 92952kb
input:
100000 1 199999 22285 45796 32145 44931 58735 13904 57137 34145 7549 92851 56319 11875 77530 85279 27040 51543 77507 94258 69266 89382 67074 61393 86160 96136 83228 74828 14858 19501 32085 73640 86885 175 27269 94391 20021 55020 45358 92588 17834 7903 55802 46033 36294 46558 73556 13747 8419 88394 1...
output:
100000
result:
ok 1 number(s): "100000"
Test #10:
score: 0
Accepted
time: 979ms
memory: 107012kb
input:
100000 1 199999 4851 52517 2577 29251 69017 1758 85855 66497 48301 50880 83742 16331 98932 9963 38731 17591 15871 13961 91302 97596 81693 57493 11891 59333 5077 41896 23575 35479 93471 65246 61977 93636 96141 34877 18202 35367 64058 34258 25589 19533 13249 91004 6442 83449 99192 61871 94537 16903 73...
output:
100000
result:
ok 1 number(s): "100000"
Test #11:
score: -100
Time Limit Exceeded
input:
100000 1 199997 4415 9894 97824 23182 2551 30097 24322 27913 64552 31862 23073 68076 28494 14953 11400 33367 14514 13085 40869 51446 63170 88054 76550 23848 22657 57759 9479 56985 96440 59224 69954 84962 55443 22220 96520 87619 31746 72821 8800 6061 36912 77572 8970 95816 32991 68335 29931 84159 333...