QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#411671#4513. Slide ParadeTobo11 1ms3916kbC++2312.0kb2024-05-15 17:30:592024-05-15 17:30:59

Judging History

你现在查看的是最新测评结果

  • [2024-05-15 17:30:59]
  • 评测
  • 测评结果:11
  • 用时:1ms
  • 内存:3916kb
  • [2024-05-15 17:30:59]
  • 提交

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...

result: