QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#411649 | #4513. Slide Parade | Tobo | 0 | 4502ms | 39728kb | C++20 | 11.2kb | 2024-05-15 17:09:33 | 2024-05-15 17:09:33 |
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);
for (int i = 1; i <= n; i++)
{
for (auto j : G[i])
{
vector<int> vis(n + 1);
auto dfs = [&](auto &dfs, int cur, int target) -> bool
{
vis[cur] = 1;
if (match[cur] == target)
return true;
for (auto to : G[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;
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';
}
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: 0
Wrong Answer
time: 1ms
memory: 3620kb
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 1 4 2 3 5 3 5 1 4 2 1 4 3 5 3 5 2 1 3 4 1 2 5 2 5 4 3 1 2 5 4 3 1 2 3 5 4 1 4 3 2 5 1 3 4 2 5 1 Case #3: 51 1 3 4 5 2 1 2 3 4 5 1 4 5 2 3 1 1 3 5 4 3 5 1 2 2 4 2 1 2 5 3 5 3 1 2 5 3 4 4 4 1 4 5 2 3 1 4 5 2 3 1 Case #4: 19 1 1 2 3 2 3 1 1 3 2 3 2 1 3 2 1 2 3 1 ...
result:
wrong answer invalid move (from 2 to 1) (test case 2)
Test #2:
score: 0
Wrong Answer
time: 4502ms
memory: 39728kb
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: 991021 1 58 94 133 19 116 73 75 102 15 99 119 146 82 104 57 173 168 165 170 88 67 46 138 194 93 62 131 70 157 63 150 106 120 100 38 10 21 107 103 161 3 90 162 23 56 66 140 40 125 74 32 17 89 167 27 166 9 156 78 85 163 81 86 139 79 6 11 188 117 195 65 77 135 114 111 92 105 31 136 149 18 5 83...
result:
wrong answer invalid move (from 1 to 58) (test case 1)