結果

問題 No.922 東北きりきざむたん
ユーザー aa
提出日時 2019-11-09 01:52:42
言語 C++14
(gcc 13.2.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 5,805 bytes
コンパイル時間 2,635 ms
コンパイル使用メモリ 192,524 KB
実行使用メモリ 65,916 KB
最終ジャッジ日時 2023-10-13 06:33:51
合計ジャッジ時間 8,000 ms
ジャッジサーバーID
(参考情報)
judge15 / judge13
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,352 KB
testcase_01 AC 2 ms
4,352 KB
testcase_02 AC 2 ms
4,348 KB
testcase_03 AC 1 ms
4,352 KB
testcase_04 AC 2 ms
4,348 KB
testcase_05 AC 1 ms
4,348 KB
testcase_06 AC 2 ms
4,348 KB
testcase_07 AC 2 ms
4,348 KB
testcase_08 AC 2 ms
4,352 KB
testcase_09 WA -
testcase_10 WA -
testcase_11 WA -
testcase_12 AC 31 ms
23,024 KB
testcase_13 AC 18 ms
8,548 KB
testcase_14 WA -
testcase_15 AC 22 ms
23,864 KB
testcase_16 WA -
testcase_17 WA -
testcase_18 WA -
testcase_19 WA -
testcase_20 WA -
testcase_21 WA -
testcase_22 WA -
testcase_23 WA -
testcase_24 AC 264 ms
47,076 KB
testcase_25 AC 257 ms
48,200 KB
testcase_26 AC 265 ms
48,124 KB
testcase_27 AC 265 ms
48,244 KB
testcase_28 AC 71 ms
28,156 KB
testcase_29 AC 270 ms
65,916 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

//#define _GLIBCXX_DEBUG
#include "bits/stdc++.h"

using namespace std;

//------------------------------- Libraries --------------------------------//

class UnionFind
{
    vector<int> par;

public:
    UnionFind(int n) : par(n, -1) {}

    int root(int x)
    {
        if (par[x] < 0)
            return x;
        else
            return par[x] = root(par[x]);
    }

    inline bool same(int u, int v)
    {
        return root(u) == root(v);
    }

    bool merge(int x, int y)
    {
        x = root(x);
        y = root(y);
        if (x == y)
            return false;
        if (par[x] > par[y])
            swap(x, y);
        par[x] += par[y];
        par[y] = x;
        return true;
    }

    int size(int x) { return -par[root(x)]; }
};

class LowestCommonAncestor
{
    //2^k >= n
    int n, k;
    vector<vector<int>> g, par;
    vector<int> dis;

    inline void build()
    {
        this->calc();
        this->setpar();
    }

    void calc(int v = 0, int p = -1)
    {
        this->par[0][v] = p;
        for (int nv : this->g[v])
        {
            if (nv != p)
            {
                this->dis[nv] = this->dis[v] + 1;
                this->calc(nv, v);
            }
        }
    }

    void setpar()
    {
        for (int i = 0; i < this->k; i++)
        {
            for (int v = 0; v < this->n; v++)
            {
                if (this->par[i][v] != -1)
                {
                    this->par[i + 1][v] = this->par[i][par[i][v]];
                }
            }
        }
    }

public:
    LowestCommonAncestor(int n_, vector<vector<int>> &g_) : n(n_), g(g_)
    {
        k = log2(n + 1);
        this->par.resize(k + 1, vector<int>(n, -1));
        dis.resize(n);
        this->build();
    }

    int get(int u, int v)
    {
        //dis[u] <= dis[v]
        if (this->dis[u] > this->dis[v])
        {
            swap(u, v);
        }
        int d = this->dis[v] - this->dis[u];
        for (int i = k; i >= 0; i--)
        {
            if (d >> i & 1)
            {
                v = this->par[i][v];
            }
        }
        if (u == v)
        {
            return v;
        }
        for (int i = k; i >= 0; i--)
        {
            if (this->par[i][u] != this->par[i][v])
            {
                u = this->par[i][u];
                v = this->par[i][v];
            }
        }
        return this->par[0][v];
    }

    int dist(int u, int v)
    {
        return this->dis[u] + this->dis[v] - 2 * dis[this->get(u, v)];
    }
};

//verified @ https://onlinejudge.u-aizu.ac.jp/status/users/sifi_border/submissions/1/GRL_5_C/judge/3883181/C++14
//verified @ https://atcoder.jp/contests/abc014/submissions/7617701

//------------------------------- Type Names -------------------------------//

using i64 = int_fast64_t;

using seika = string;
//akari : 1D, yukari : 2D, maki : 3D vector
template <class kizuna>
using akari = vector<kizuna>;
template <class yuzuki>
using yukari = akari<akari<yuzuki>>;
template <class tsurumaki>
using maki = akari<yukari<tsurumaki>>;
//akane : ascending order, aoi : decending order
template <class kotonoha>
using akane = priority_queue<kotonoha, akari<kotonoha>, greater<kotonoha>>;
template <class kotonoha>
using aoi = priority_queue<kotonoha>;

//------------------------------- Dubug Functions ---------------------------//
inline void print()
{
    cout << endl;
}
template <typename First, typename... Rest>
void print(const First &first, const Rest &... rest)
{
    cout << first << ' ';
    print(rest...);
}
//------------------------------- Solver ------------------------------------//

void solve()
{
    int n, m, q;
    cin >> n >> m >> q;
    yukari<int> g(n);
    UnionFind uf(n);
    for (int i = 0; i < m; i++)
    {
        int u, v;
        cin >> u >> v;
        u--, v--;
        g[u].push_back(v);
        g[v].push_back(u);
        uf.merge(u, v);
    }
    LowestCommonAncestor lca(n, g);
    akari<i64> ws(n);
    i64 ans = 0;
    for (int i = 0; i < q; i++)
    {
        int a, b;
        cin >> a >> b;
        a--, b--;
        if (uf.same(a, b))
        {
            ans += lca.dist(a, b);
        }
        else
        {
            ws[a]++;
            ws[b]++;
        }
    }
    akari<map<int, pair<i64, i64>>> dp(n);
    auto calc = [&](auto &&calc, int v, int p, bool flag) -> pair<i64, i64> {
        if (dp[v].count(p))
        {
            return dp[v][p];
        }
        //res = {val, dif}
        pair<i64, i64> res = make_pair(0, ws[v]);
        if (flag || p == -1)
        {
            for (auto nv : g[v])
            {
                if (nv == p)
                {
                    continue;
                }
                auto chi = calc(calc, nv, v, flag);
                res.first += chi.first + chi.second;
                res.second += chi.second;
            }
        }
        else
        {
            auto par = calc(calc, p, v, 0);
            auto ard = calc(calc, v, -1, 0);
            res.first = ard.first - par.first - par.second;
            res.second = ard.second - par.second;
        }
        return dp[v][p] = res;
    };
    akari<int> used(n);
    //uf の代表に対して呼ぶ
    for (int v = 0; v < n; v++)
    {
        int p = uf.root(v);
        if (used[p])
        {
            continue;
        }
        used[p] = 1;
        calc(calc, p, -1, 1);
    }
    akari<i64> sum(n, 1e15);
    for (int v = 0; v < n; v++)
    {
        sum[uf.root(v)] = min(sum[uf.root(v)], calc(calc, v, -1, 0).first);
        //print(v, calc(calc, v, -1, 0).first, calc(calc, v, -1, 0).second);
    }
    for (int v = 0; v < n; v++)
    {
        if (!used[v])
        {
            continue;
        }
        ans += sum[v];
    }
    cout << ans << endl;
}

int main()
{
    solve();
    return 0;
}
0