QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#411675 | #4513. Slide Parade | Tobo | 35 ✓ | 2095ms | 39540kb | C++23 | 11.3kb | 2024-05-15 17:34:10 | 2024-05-15 17:34:11 |
Judging History
answer
#include <bits/stdc++.h>
using i64 = long long;
using namespace std;
typedef long long flow_t;
typedef long long cost_t;
const flow_t inf_flow = 1e18;
const cost_t inf_cost = 1e18;
struct CostEdge
{
int from, to;
cost_t cost;
flow_t cap, low = 0, flow = 0;
};
int num_node(const std::vector<CostEdge> &edges)
{
int n = 0;
for (const auto &e : edges)
n = std::max({n, e.from, e.to});
return n;
}
std::pair<flow_t, cost_t> get_flow(const std::vector<CostEdge> &edges, int s)
{
flow_t flow = 0;
cost_t cost = 0;
for (const auto &e : edges)
{
if (e.from == s)
flow += e.flow;
cost += e.flow * e.cost;
}
return {flow, cost};
}
struct CostFlow
{
struct Edge
{
int from, to;
cost_t cost;
flow_t cap;
};
int n;
std::vector<std::vector<int>> eid;
std::vector<Edge> edge;
void build(const std::vector<CostEdge> &edges)
{
n = num_node(edges);
eid.assign(n + 1, {});
edge.clear();
int num_edges = 0;
for (const auto &e : edges)
{
eid[e.from].push_back(num_edges++);
edge.push_back({e.from, e.to, e.cost, e.cap - e.flow});
eid[e.to].push_back(num_edges++);
edge.push_back({e.to, e.from, -e.cost, e.flow});
}
}
std::vector<cost_t> dis;
std::vector<int> pre;
bool spfa(int s, int t)
{
if (s > n || t > n)
return false;
dis.assign(n + 1, inf_cost);
pre.assign(n + 1, 0);
std::vector<bool> inque(n + 1);
std::queue<int> que;
dis[s] = 0;
que.push(s);
inque[s] = true;
while (que.size())
{
int u = que.front();
// cerr << 'u' << ' ' << u << endl;
que.pop();
inque[u] = false;
for (auto i : eid[u])
{
const auto &e = edge[i];
if (e.cap && dis[e.to] > dis[u] + e.cost)
{
dis[e.to] = dis[u] + e.cost;
pre[e.to] = i;
if (!inque[e.to])
{
que.push(e.to);
inque[e.to] = true;
}
}
}
}
return dis[t] < inf_cost;
}
std::pair<flow_t, cost_t> maxflow(int s, int t)
{
flow_t flow = 0;
cost_t cost = 0;
while (spfa(s, t))
{
flow_t detf = inf_flow;
cost_t detc = 0;
for (int u = t, i = pre[u]; u != s; u = edge[i].from, i = pre[u])
{
detf = std::min(detf, edge[i].cap);
detc += edge[i].cost;
}
for (int u = t, i = pre[u]; u != s; u = edge[i].from, i = pre[u])
{
edge[i].cap -= detf;
edge[i ^ 1].cap += detf;
}
flow += detf;
cost += detf * detc;
}
return {flow, cost};
}
std::vector<CostEdge> to_edge()
{
std::vector<CostEdge> edges;
for (int i = 0; i < edge.size(); i += 2)
edges.push_back({
.from = edge[i].from,
.to = edge[i].to,
.cost = edge[i].cost,
.cap = edge[i].cap + edge[i ^ 1].cap,
.flow = edge[i ^ 1].cap,
});
return edges;
}
};
struct Processor
{
std::vector<bool> neg;
std::vector<flow_t> low;
std::vector<flow_t> excess;
void init(std::vector<CostEdge> &edges)
{
int n = num_node(edges);
neg.clear();
neg.reserve(edges.size());
low.clear();
low.reserve(edges.size());
excess.assign(n + 1, 0);
}
void rmv_low(std::vector<CostEdge> &edges)
{
for (auto &e : edges)
{
low.push_back(e.low);
if (e.flow >= e.low)
{
e.flow -= e.low;
}
else
{
excess[e.from] -= e.low - e.flow;
excess[e.to] += e.low - e.flow;
e.flow = 0;
}
e.cap -= e.low;
e.low = 0;
}
}
void add_low(std::vector<CostEdge> &edges)
{
reverse(low.begin(), low.end());
for (auto &e : edges)
{
e.low = low.back();
e.flow += e.low;
e.cap += e.low;
low.pop_back();
}
}
void rmv_neg(std::vector<CostEdge> &edges)
{
for (auto &e : edges)
{
neg.push_back(e.cost < 0);
if (e.cost < 0)
{
excess[e.from] -= e.cap - e.flow;
excess[e.to] += e.cap - e.flow;
e.flow = e.cap;
}
if (e.cost > 0)
{
excess[e.from] += e.flow;
excess[e.to] -= e.flow;
e.flow = 0;
}
}
}
};
bool excess_flow(std::vector<CostEdge> &edges,
const std::vector<flow_t> &excess)
{
int n = num_node(edges), m = edges.size();
for (int i = 1; i <= n; i++)
{
if (excess[i] > 0)
edges.push_back({.from = n + 1, .to = i, .cost = 0, .cap = excess[i]});
if (excess[i] < 0)
edges.push_back({.from = i, .to = n + 2, .cost = 0, .cap = -excess[i]});
}
CostFlow g;
g.build(edges);
g.maxflow(n + 1, n + 2);
edges = g.to_edge();
for (int i = m; i < edges.size(); i++)
if (edges[i].flow != edges[i].cap)
return false;
edges.resize(m);
return true;
}
std::optional<std::pair<flow_t, cost_t>> feasible_flow(
std::vector<CostEdge> &edges, int s = 0, int t = 0)
{
if (s && t)
edges.push_back({.from = t, .to = s, .cost = 0, .cap = inf_flow});
Processor p;
p.init(edges);
p.rmv_low(edges);
p.rmv_neg(edges);
if (!excess_flow(edges, p.excess))
return std::nullopt;
if (s && t)
edges.pop_back();
p.add_low(edges);
return get_flow(edges, s);
}
std::optional<std::pair<flow_t, cost_t>> maximum_flow(
std::vector<CostEdge> &edges, int s, int t)
{
edges.push_back({.from = t, .to = s, .cost = 0, .cap = inf_flow});
Processor p;
p.init(edges);
p.rmv_low(edges);
p.rmv_neg(edges);
if (!excess_flow(edges, p.excess))
return std::nullopt;
edges.pop_back();
CostFlow g;
g.build(edges);
g.maxflow(s, t);
edges = g.to_edge();
p.add_low(edges);
return get_flow(edges, s);
}
std::optional<std::pair<flow_t, cost_t>> minimum_flow(
std::vector<CostEdge> &edges, int s, int t)
{
edges.push_back({.from = t, .to = s, .cost = 0, .cap = inf_flow});
Processor p;
p.init(edges);
p.rmv_low(edges);
p.rmv_neg(edges);
if (!excess_flow(edges, p.excess))
return std::nullopt;
edges.pop_back();
CostFlow g;
for (auto &e : edges)
e.cost = -e.cost;
Processor q;
q.rmv_neg(edges);
excess_flow(edges, q.excess);
g.build(edges);
g.maxflow(t, s);
edges = g.to_edge();
for (auto &e : edges)
e.cost = -e.cost;
p.add_low(edges);
return get_flow(edges, s);
}
void solve()
{
int n, m;
cin >> n >> m;
int s = 0, t = n * 2 + 1;
vector<int> head(t + 1, -1), cap, to, nxt;
auto add = [&](int x, int y, int z)
{
to.push_back(y);
cap.push_back(z);
nxt.push_back(head[x]);
head[x] = to.size() - 1;
to.push_back(x);
cap.push_back(0);
nxt.push_back(head[y]);
head[y] = to.size() - 1;
};
vector<vector<int>> G(n + 1);
for (int i = 1, u, v; i <= m; i++)
{
cin >> u >> v;
G[u].push_back(v);
add(u, v + n, 1);
}
for (int i = 1; i <= n; i++)
add(s, i, 1), add(i + n, t, 1);
vector<int> g(t + 1), dis(t + 1);
auto bfs = [&]() -> bool
{
dis.assign(t + 1, -1);
dis[s] = 0;
queue<int> que;
que.push(s);
while (!que.empty())
{
int cur = que.front();
que.pop();
g[cur] = head[cur];
for (int p = head[cur]; ~p; p = nxt[p])
{
if (cap[p] && dis[to[p]] == -1)
{
dis[to[p]] = dis[cur] + 1;
que.push(to[p]);
}
}
}
return dis[t] != -1;
};
auto dfs = [&](auto &dfs, int cur, int flow) -> int
{
if (cur == t)
return flow;
int used = 0;
for (int &p = g[cur]; ~p; p = nxt[p])
{
if (cap[p] && dis[to[p]] == dis[cur] + 1)
{
int k = dfs(dfs, to[p], min(flow - used, cap[p]));
used += k;
cap[p] -= k, cap[p ^ 1] += k;
if (used == flow)
break;
}
}
return used;
};
int match_cnt = 0;
while (bfs())
match_cnt += dfs(dfs, s, 1e9);
if (match_cnt < n)
{
cout << "IMPOSSIBLE\n";
return;
}
vector<int> match(n + 1);
for (int i = 1; i <= n; i++)
{
for (int p = head[i]; ~p; p = nxt[p])
{
if (to[p] >= n + 1 && to[p] <= n * 2 && !cap[p])
match[to[p] - n] = i;
}
}
vector<vector<int>> adj(n + 1);
vector<int> vis(n + 1);
for (int i = 1; i <= n; i++)
{
for (auto j : G[i])
{
vis.assign(n + 1, 0);
auto dfs = [&](auto &dfs, int cur, int target) -> bool
{
vis[cur] = 1;
if (match[cur] == target)
return true;
for (auto to : G[match[cur]])
{
if (vis[to] || !dfs(dfs, to, target))
continue;
match[to] = match[cur], match[cur] = target;
return true;
}
return false;
};
if (!dfs(dfs, j, i))
{
cout << "IMPOSSIBLE\n";
return;
}
for (int k = 1; k <= n; k++)
adj[match[k]].push_back(k);
}
}
vector<int> path{1};
auto dfs1 = [&](auto &dfs1, int cur) -> void
{
while (!adj[cur].empty())
{
auto lst = adj[cur].back();
adj[cur].pop_back();
dfs1(dfs1, lst);
path.push_back(cur);
}
};
dfs1(dfs1, 1);
if (path.size() != n * m + 1)
{
cout << "IMPOSSIBLE\n";
return;
}
reverse(path.begin(), path.end());
cout << n * m + 1 << '\n';
for (int i : path)
cout << i << ' ';
cout << '\n';
}
/*
1
3 6
1 2
1 3
2 1
2 3
3 1
3 2
*/
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
for (int _ = 1; _ <= t; _++)
{
cout << "Case #" << _ << ": ";
solve();
}
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 11
Accepted
time: 1ms
memory: 3616kb
input:
100 5 8 1 2 1 3 1 4 1 5 2 1 3 1 4 1 5 1 5 10 1 3 1 4 2 3 2 5 3 1 3 4 3 5 4 2 5 1 5 3 5 10 1 4 2 3 2 5 3 1 3 5 4 2 4 3 4 5 5 1 5 2 3 6 1 2 1 3 2 1 2 3 3 1 3 2 5 10 1 2 1 5 2 3 2 4 3 1 4 3 4 5 5 2 5 3 5 4 4 10 1 2 1 3 1 4 2 1 2 3 2 4 3 1 3 4 4 2 4 3 5 10 1 2 1 3 2 1 2 4 3 1 3 5 4 2 4 5 5 3 5 4 5 10 1 ...
output:
Case #1: IMPOSSIBLE Case #2: 51 1 4 2 5 3 1 4 2 3 5 1 4 2 3 5 1 4 2 3 5 1 3 4 2 5 1 4 2 5 3 1 4 2 5 3 1 4 2 3 5 1 4 2 5 3 1 3 4 2 5 1 Case #3: 51 1 4 3 1 4 2 5 2 3 5 1 4 5 2 3 1 4 3 1 4 2 5 2 3 5 1 4 2 3 5 1 4 3 1 4 3 1 4 5 2 5 2 5 2 3 1 4 5 2 3 1 Case #4: 19 1 3 2 1 2 3 1 2 3 1 3 2 1 3 2 1 2 3 1 ...
result:
ok (100 test cases)
Test #2:
score: 24
Accepted
time: 2095ms
memory: 39540kb
input:
100 199 4980 1 95 1 96 1 105 1 124 1 130 1 131 1 135 1 137 1 139 1 140 1 141 1 147 1 155 1 172 1 174 1 179 1 183 1 188 1 193 1 196 1 197 2 3 2 5 2 13 2 14 2 17 2 20 2 24 2 26 2 30 2 41 2 44 2 45 2 52 2 56 2 67 2 70 2 71 2 74 2 78 2 84 2 85 2 90 2 92 2 93 2 97 2 107 2 111 2 113 2 122 2 124 2 128 2 13...
output:
Case #1: IMPOSSIBLE Case #2: IMPOSSIBLE Case #3: 1000001 1 71 5 27 192 189 54 39 176 58 130 68 105 36 97 7 132 86 20 108 31 49 133 160 129 10 40 107 94 185 167 89 12 51 79 18 25 119 175 136 141 187 21 131 181 2 183 110 151 196 163 26 113 117 1 61 82 61 83 37 149 6 90 46 123 57 50 128 148 81 78 177 3...
result:
ok (100 test cases)