QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#411671 | #4513. Slide Parade | Tobo | 11 | 1ms | 3916kb | C++23 | 12.0kb | 2024-05-15 17:30:59 | 2024-05-15 17:30:59 |
Judging History
answer
#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx2")
#pragma GCC optimize(3, "inline")
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 = [&](int s, int t) -> bool
{
dis.assign(n * 2 + 2, -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 t, 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], t, 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(s, t))
match_cnt += dfs(dfs, s, t, 1e9);
if (match_cnt < n)
{
cout << "IMPOSSIBLE\n";
return;
}
vector<int> match(n + 1);
auto go = [&]()
{
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;
}
}
};
go();
vector<vector<int>> adj(n + 1);
for (int i = 1; i <= n; i++)
{
for (auto j : G[i])
{
if (match[j] != i)
{
if (!bfs(j + n, i))
{
cout << "IMPOSSIBLE\n";
return;
}
dfs(dfs, j + n, i, 1);
bfs(i, j + n);
dfs(dfs, i, j + n, 1);
go();
assert(match[j] == i);
}
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';
}
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
for (int _ = 1; _ <= t; _++)
{
cout << "Case #" << _ << ": ";
solve();
}
}
详细
Test #1:
score: 11
Accepted
time: 1ms
memory: 3916kb
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 3 4 2 5 1 4 2 3 5 1 4 2 3 5 1 3 4 2 5 1 Case #3: 51 1 4 5 2 3 1 4 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: 0
Time Limit Exceeded
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 156 20 139 125 177 61 198 76 131 197 185 23 64 93 140 46 42 3 31 109 49 154 45 54 165 97 8 172 28 199 200 169 81 9 37 157 179 80 24 63 43 38 158 175 84 120 90 88 107 32 103 75 6 183 194 182 40 130 149 66 59 170 95 191 10 189 119 48 173 16 69...